{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Title: #Count Pairs With XOR in a Range"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Difficulty: #Hard"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Category Title: #Algorithms"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Tag Slug: #bit-manipulation #trie #array"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Name Translated: #位运算 #字典树 #数组"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Solution Name: countPairs"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Translated Title: #统计异或值在范围内的数对有多少"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Translated Content:\n",
    "<p>给你一个整数数组 <code>nums</code> （下标 <strong>从 0 开始</strong> 计数）以及两个整数：<code>low</code> 和 <code>high</code> ，请返回 <strong>漂亮数对</strong> 的数目。</p>\n",
    "\n",
    "<p><strong>漂亮数对</strong> 是一个形如 <code>(i, j)</code> 的数对，其中 <code>0 &lt;= i &lt; j &lt; nums.length</code> 且 <code>low &lt;= (nums[i] XOR nums[j]) &lt;= high</code> 。</p>\n",
    "\n",
    "<p> </p>\n",
    "\n",
    "<p><strong>示例 1：</strong></p>\n",
    "\n",
    "<pre><strong>输入：</strong>nums = [1,4,2,7], low = 2, high = 6\n",
    "<strong>输出：</strong>6\n",
    "<strong>解释：</strong>所有漂亮数对 (i, j) 列出如下：\n",
    "    - (0, 1): nums[0] XOR nums[1] = 5 \n",
    "    - (0, 2): nums[0] XOR nums[2] = 3\n",
    "    - (0, 3): nums[0] XOR nums[3] = 6\n",
    "    - (1, 2): nums[1] XOR nums[2] = 6\n",
    "    - (1, 3): nums[1] XOR nums[3] = 3\n",
    "    - (2, 3): nums[2] XOR nums[3] = 5\n",
    "</pre>\n",
    "\n",
    "<p><strong>示例 2：</strong></p>\n",
    "\n",
    "<pre><strong>输入：</strong>nums = [9,8,4,2,1], low = 5, high = 14\n",
    "<strong>输出：</strong>8\n",
    "<strong>解释：</strong>所有漂亮数对 (i, j) 列出如下：\n",
    "​​​​​    - (0, 2): nums[0] XOR nums[2] = 13\n",
    "    - (0, 3): nums[0] XOR nums[3] = 11\n",
    "    - (0, 4): nums[0] XOR nums[4] = 8\n",
    "    - (1, 2): nums[1] XOR nums[2] = 12\n",
    "    - (1, 3): nums[1] XOR nums[3] = 10\n",
    "    - (1, 4): nums[1] XOR nums[4] = 9\n",
    "    - (2, 3): nums[2] XOR nums[3] = 6\n",
    "    - (2, 4): nums[2] XOR nums[4] = 5</pre>\n",
    "\n",
    "<p> </p>\n",
    "\n",
    "<p><strong>提示：</strong></p>\n",
    "\n",
    "<ul>\n",
    "\t<li><code>1 &lt;= nums.length &lt;= 2 * 10<sup>4</sup></code></li>\n",
    "\t<li><code>1 &lt;= nums[i] &lt;= 2 * 10<sup>4</sup></code></li>\n",
    "\t<li><code>1 &lt;= low &lt;= high &lt;= 2 * 10<sup>4</sup></code></li>\n",
    "</ul>\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Description: [count-pairs-with-xor-in-a-range](https://leetcode.cn/problems/count-pairs-with-xor-in-a-range/description/)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Solutions: [count-pairs-with-xor-in-a-range](https://leetcode.cn/problems/count-pairs-with-xor-in-a-range/solutions/)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "test_cases = ['[1,4,2,7]\\n2\\n6', '[9,8,4,2,1]\\n5\\n14']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, nums1: List[int], nums2: List[int]) -> int:\n",
    "        n = len(nums1)\n",
    "        for i in range(n):\n",
    "            nums1[i] = nums1[i] - nums2[i]\n",
    "        nums1.sort()\n",
    "        left = 0\n",
    "        right = n-1\n",
    "        res = 0\n",
    "        while left<right:\n",
    "            target = nums1[left]+nums1[right]\n",
    "            if target>0:\n",
    "                res = res+right - left\n",
    "                right-=1\n",
    "            else:\n",
    "                left+=1\n",
    "        return res\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "\"\"\"\n",
    "int n = nums1.size();\n",
    "        for(int i=0;i<nums1.size();i++){\n",
    "            nums1[i]-=nums2[i];\n",
    "        }\n",
    "        sort(nums1.begin(),nums1.end());\n",
    "        int left=0,right = n-1;\n",
    "        long long res = 0;\n",
    "        while(left<right){\n",
    "            long long target = nums1[left]+nums1[right];\n",
    "            if(target>0) {\n",
    "                res+=right-left;\n",
    "                right--;\n",
    "            } else{\n",
    "                left++;\n",
    "            }\n",
    "        }\n",
    "        return  res;\n",
    "\n",
    "\"\"\"\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, nums1: List[int], nums2: List[int]) -> int:\n",
    "        n = len(nums1)\n",
    "        for i in range(n):\n",
    "            nums1[i] = nums1[i] - nums2[i]\n",
    "        nums1.sort()\n",
    "        left = 0\n",
    "        right = n-1\n",
    "        res = 0\n",
    "        while left<right:\n",
    "            target = nums1[left]+nums1[right]\n",
    "            if target>0:\n",
    "                res = res+right - left\n",
    "                right-=1\n",
    "            else:\n",
    "                left+=1\n",
    "        return res"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, nums1: List[int], nums2: List[int]) -> int:\n",
    "        n = len(nums1)\n",
    "        for i in range(n):\n",
    "            nums1[i] = nums1[i] - nums2[i]\n",
    "        nums1.sort()\n",
    "        left = 0\n",
    "        right = n-1\n",
    "        res = 0\n",
    "        while left<right:\n",
    "            target = nums1[left]+nums1[right]\n",
    "            if target>0:\n",
    "                res = res+right - left\n",
    "                right-=1\n",
    "            else:\n",
    "                left+=1\n",
    "        return res"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, nums1: List[int], nums2: List[int]) -> int:\n",
    "        n = len(nums1)\n",
    "        res = [nums1[i] - nums2[i] for i in range(n)]\n",
    "        res.sort()\n",
    "        l, r = 0, n - 1\n",
    "        ans = 0\n",
    "        while l < r:\n",
    "            while r > l and res[l] + res[r] > 0:\n",
    "                r -= 1\n",
    "            ans += n - r - 1\n",
    "            l += 1\n",
    "            if l >= r:\n",
    "                ans += (n - l - 1) * (n - l) // 2\n",
    "        return ans"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, nums1: List[int], nums2: List[int]) -> int:\n",
    "        n = len(nums1)\n",
    "        arr = sorted(x - y for x, y in zip(nums1, nums2))\n",
    "        ans = 0\n",
    "        for x in arr:\n",
    "            ans += n - bisect_right(arr, -x) - (x > 0)\n",
    "        return ans // 2\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "from sortedcontainers import SortedList\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, nums1: List[int], nums2: List[int]) -> int:\n",
    "        ans = 0\n",
    "        n = len(nums1)\n",
    "        sl = SortedList()\n",
    "        for i in range(n):\n",
    "            tmp = nums1[i] - nums2[i]\n",
    "            idx = sl.bisect_left(tmp)\n",
    "            ans += idx \n",
    "            sl.add(-tmp)\n",
    "        return ans"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, nums1: List[int], nums2: List[int]) -> int:\n",
    "        diff = sorted([nums1[i] - nums2[i] for i in range(len(nums1))])\n",
    "        l, r = 0, len(nums1)-1\n",
    "        ans = 0\n",
    "        while l < r:\n",
    "            if diff[r] + diff[l] > 0:\n",
    "                ans += (r-l)\n",
    "                r -= 1\n",
    "            else:\n",
    "                l += 1\n",
    "\n",
    "        return ans\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, nums1: List[int], nums2: List[int]) -> int:\n",
    "        # n=len(nums1)\n",
    "        dif = sorted([nums1[j]-nums2[j] for j in range(len(nums1))])\n",
    "        return sum(len(nums1)-max(j+1,bisect_right(dif,-dif[j])) for j in range(len(nums1)))\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, n: int, edges: List[List[int]], queries: List[int]) -> List[int]:\n",
    "        deg = Counter(chain(*edges))\n",
    "        cnt = Counter((min(x, y), max(x, y)) for x, y in edges)\n",
    "        a = sorted(deg[x] + deg[y] for x, y in cnt)\n",
    "        b = sorted(deg[x] + deg[y] - cnt[x, y] for x, y in cnt)\n",
    "        sd = sorted(deg.values())\n",
    "        m = len(sd)\n",
    "        return [(n - m) * (m - bisect_right(sd, q)) + m * m - sum(bisect_right(sd, q - x, i + 1) for i, x in enumerate(sd)) + bisect_right(a, q) - bisect_right(b, q) for q in queries]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, n: int, edges: List[List[int]], queries: List[int]) -> List[int]:\n",
    "        deg = Counter(chain(*edges))\n",
    "        cnt = Counter(tuple(sorted(t)) for t in edges)\n",
    "        a = sorted(deg[x] + deg[y] for x, y in cnt)\n",
    "        b = sorted(deg[x] + deg[y] - cnt[x, y] for x, y in cnt)\n",
    "        sd = sorted(deg.values())\n",
    "        m = len(sd)\n",
    "        return [(n - m) * (m - bisect_right(sd, q)) + m * m - sum(bisect_right(sd, q - x, i + 1) for i, x in enumerate(sd)) + bisect_right(a, q) - bisect_right(b, q) for q in queries]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, n: int, edges: List[List[int]], queries: List[int]) -> List[int]:\n",
    "        nums=[0 for _ in range(n+1)]\n",
    "        d=Counter(tuple(sorted(e)) for e in edges)\n",
    "        print(le)\n",
    "        for li in edges:\n",
    "            nums[li[0]]+=1\n",
    "            nums[li[1]]+=1\n",
    "            if li[0]>li[1]:\n",
    "                li[0],li[1]=li[1],li[0]\n",
    "                \n",
    "        ans=[0 for _ in queries]\n",
    "        nso=sorted(nums)\n",
    "        for j,q in enumerate(queries):\n",
    "            l,r,a=1,n,0\n",
    "            while l<=r:\n",
    "                if nso[l]+nso[r]<=q:\n",
    "                    l+=1\n",
    "                else:\n",
    "                    a+=r-l\n",
    "                    r-=1\n",
    "            for (x,y),value in d.items():\n",
    "                if q<nums[x]+nums[y]<=q+value:\n",
    "                    a-=1\n",
    "            ans[j]=a\n",
    "        return ans"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, n: int, edges: List[List[int]], queries: List[int]) -> List[int]:\n",
    "        d = Counter()\n",
    "        edgesCount = [0 for _ in range(n)]\n",
    "        for (x,y) in edges:\n",
    "            x -= 1\n",
    "            y -= 1\n",
    "            edgesCount[x]+=1\n",
    "            edgesCount[y]+=1\n",
    "            if x > y:\n",
    "                x, y = y, x\n",
    "            d[x * n + y] += 1\n",
    "        sortedges = sorted(edgesCount)\n",
    "        ans = []\n",
    "        for querie in queries:\n",
    "            total = 0\n",
    "            for i in range(n):\n",
    "                index = bisect_right(sortedges, querie - sortedges[i], i+1)\n",
    "                total += n - index\n",
    "            for (idx,val) in d.items():\n",
    "                x, y = idx//n, idx%n\n",
    "                if edgesCount[x] + edgesCount[y] > querie and edgesCount[x] + edgesCount[y] - val <= querie:\n",
    "                    total-=1\n",
    "            ans.append(total)\n",
    "        return ans\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, n: int, edges: List[List[int]], queries: List[int]) -> List[int]:\n",
    "        from collections import Counter\n",
    "        deg = [0] * (n+1)\n",
    "        for x,y in edges:\n",
    "            deg[x]+=1\n",
    "            deg[y]+=1\n",
    "        \n",
    "        cnt_e = Counter([tuple(sorted(e)) for e in edges])\n",
    "        ans = [0]*len(queries)\n",
    "        sorted_deg = sorted(deg)\n",
    "        for j,q in enumerate(queries):\n",
    "            left,right=1,n\n",
    "            while left<right:\n",
    "                if sorted_deg[left] + sorted_deg[right] <= q:\n",
    "                    left += 1\n",
    "                else:\n",
    "                    ans[j] += right - left\n",
    "                    right -= 1\n",
    "            for (x,y),c in cnt_e.items():\n",
    "                if q<deg[x]+deg[y]<=q+c:\n",
    "                    ans[j]-=1\n",
    "        return ans\n",
    "        \n",
    "\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, n: int, edges: List[List[int]], queries: List[int]) -> List[int]:\n",
    "        degrees = [0] * (n + 1)\n",
    "        edge_cnt = defaultdict(int)\n",
    "        for u, v in edges:\n",
    "            if u > v:\n",
    "                u, v = v, u\n",
    "            degrees[u] += 1\n",
    "            degrees[v] += 1\n",
    "            edge_cnt[u << 16 | v] += 1\n",
    "\n",
    "        sorted_degrees = sorted(degrees)\n",
    "        ans = [0] * len(queries)\n",
    "        for i, q in enumerate(queries):\n",
    "            l, r = 1, n\n",
    "            while l < r:\n",
    "                if sorted_degrees[l] + sorted_degrees[r] <= q:\n",
    "                    l += 1\n",
    "                else:\n",
    "                    ans[i] += r - l\n",
    "                    r -= 1\n",
    "            for k, c in edge_cnt.items():\n",
    "                u, v = k >> 16, k & 0xffff\n",
    "                if q < degrees[u] + degrees[v] <= q + c:\n",
    "                    ans[i] -= 1\n",
    "        return ans"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# class Solution:\n",
    "#     def countPairs(self, n: int, edges: List[List[int]], queries: List[int]) -> List[int]:\n",
    "        # degree = [0 for _ in range(n)]\n",
    "        # m, cnt = len(edges), {}\n",
    "        # for i in range(m):\n",
    "        #     l, r = edges[i]\n",
    "        #     degree[l - 1] += 1  # 记录每个节点的度\n",
    "        #     degree[r - 1] += 1\n",
    "        #     if l > r:  l, r = r, l\n",
    "        #     if (l, r) not in cnt:   # 记录节点的边数\n",
    "        #         cnt[(l,r)] = 1\n",
    "        #     else:\n",
    "        #         cnt[(l,r)] += 1\n",
    "\n",
    "        # answers = [0 for _ in range(len(queries))]\n",
    "        # numbers = []\n",
    "        # for i in range(n - 1):\n",
    "        #     for j in range(i+1, n):\n",
    "        #         if (i + 1, j + 1) in cnt:\n",
    "        #             numbers.append(degree[i] + degree[j] - cnt[(i + 1,j + 1)])\n",
    "        #         else:\n",
    "        #             numbers.append(degree[i] + degree[j])\n",
    "\n",
    "        # for q in range(len(queries)):\n",
    "        #     for i in range(len(numbers)):\n",
    "        #         if numbers[i] > queries[q]:\n",
    "        #             answers[q] += 1\n",
    "        # return answers\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, n: int, edges: List[List[int]], queries: List[int]) -> List[int]:\n",
    "        degree = [0 for _ in range(n)]\n",
    "        cnt = collections.defaultdict(int)\n",
    "        for edge in edges:\n",
    "            x, y = edge[0] - 1, edge[1] - 1\n",
    "            if x > y:\n",
    "                x, y = y, x\n",
    "            degree[x] += 1\n",
    "            degree[y] += 1\n",
    "            cnt[x * n + y] += 1\n",
    "\n",
    "        arr = sorted(degree)\n",
    "        ans = []\n",
    "        for bound in queries:\n",
    "            total = 0\n",
    "            j = n - 1\n",
    "            for i in range(n):\n",
    "                while j > i and arr[i] + arr[j] > bound:\n",
    "                    j -= 1\n",
    "                total += n - 1 - max(i, j)\n",
    "            for val, freq in cnt.items():\n",
    "                x, y = val // n, val % n\n",
    "                if degree[x] + degree[y] > bound and degree[x] + degree[y] - freq <= bound:\n",
    "                    total -= 1\n",
    "            ans.append(total)\n",
    "        return ans"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, n: int, edges: List[List[int]], queries: List[int]) -> List[int]:\n",
    "        degree = [0 for _ in range(n)]\n",
    "        cnt = collections.defaultdict(int)\n",
    "        for edge in edges:\n",
    "            x, y = edge[0] - 1, edge[1] - 1\n",
    "            if x > y:\n",
    "                x, y = y, x\n",
    "            degree[x] += 1\n",
    "            degree[y] += 1\n",
    "            cnt[x * n + y] += 1\n",
    "\n",
    "        arr = sorted(degree)\n",
    "        ans = []\n",
    "        for bound in queries:\n",
    "            total = 0\n",
    "            for i in range(n):\n",
    "                j = bisect_right(arr, bound - arr[i], i + 1)\n",
    "                total += n - j\n",
    "            for val, freq in cnt.items():\n",
    "                x, y = val // n, val % n\n",
    "                if degree[x] + degree[y] > bound and degree[x] + degree[y] - freq <= bound:\n",
    "                    total -= 1\n",
    "            ans.append(total)\n",
    "        return ans\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, n: int, edges: List[List[int]], queries: List[int]) -> List[int]:\n",
    "        deg = [0] *(n+1)\n",
    "        for x,y in edges:\n",
    "            deg[x] +=1\n",
    "            deg[y] +=1\n",
    "        # 统计每条边的出现次数，注意 1-2 和 2-1 算同一条边\n",
    "        cnt_e = Counter(tuple(sorted(e)) for e in edges)#类比哈希表\n",
    "\n",
    "        ans = [0]*len(queries)\n",
    "        sorted_deg = sorted(deg)\n",
    "        for j,q in enumerate(queries):\n",
    "            left,right =1,n\n",
    "            while left<right:\n",
    "                if sorted_deg[left] +sorted_deg[right] <=q:\n",
    "                    left +=1\n",
    "                else:\n",
    "                    ans[j]+=right-left\n",
    "                    right -=1\n",
    "            for (x,y) ,c in cnt_e.items():\n",
    "                if q<deg[x]+deg[y] <=q+c:\n",
    "                    ans[j] -=1\n",
    "        return ans \n",
    "    \n",
    "\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, n: int, edges: List[List[int]], queries: List[int]) -> List[int]:\n",
    "        deg=[0]*(n+1)\n",
    "        for x,y in edges:\n",
    "            deg[x]+=1\n",
    "            deg[y]+=1\n",
    "        cnt_e=Counter(tuple(sorted(e)) for e in edges)\n",
    "\n",
    "        ans=[0]*len(queries)\n",
    "        sorted_deg=sorted(deg)\n",
    "        for j,q in enumerate(queries):\n",
    "            left,right=1,n\n",
    "            while left<right:\n",
    "                if sorted_deg[left]+sorted_deg[right]<=q:\n",
    "                    left+=1\n",
    "                else:\n",
    "                    ans[j]+=right-left\n",
    "                    right-=1\n",
    "            for (x,y),c in cnt_e.items():\n",
    "                if q<deg[x]+deg[y]<=q+c:\n",
    "                    ans[j]-=1\n",
    "        return ans\n",
    "\n",
    "    "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, n: int, edges: List[List[int]], queries: List[int]) -> List[int]:\n",
    "        deg = [0] * (n + 1)\n",
    "        cnt_e = dict()  # 比 Counter 快一点\n",
    "        for x, y in edges:\n",
    "            if x > y: x, y = y, x\n",
    "            deg[x] += 1\n",
    "            deg[y] += 1\n",
    "            cnt_e[(x, y)] = cnt_e.get((x, y), 0) + 1\n",
    "        cnt_deg = Counter(deg[1:])\n",
    "\n",
    "        # 2)\n",
    "        cnts = [0] * (max(deg) * 2 + 2)\n",
    "        for deg1, c1 in cnt_deg.items():\n",
    "            for deg2, c2 in cnt_deg.items():\n",
    "                if deg1 < deg2:\n",
    "                    cnts[deg1 + deg2] += c1 * c2\n",
    "                elif deg1 == deg2:\n",
    "                    cnts[deg1 + deg2] += c1 * (c1 - 1) // 2\n",
    "\n",
    "        # 3)\n",
    "        for (x, y), c in cnt_e.items():\n",
    "            s = deg[x] + deg[y]\n",
    "            cnts[s] -= 1\n",
    "            cnts[s - c] += 1\n",
    "\n",
    "        # 4) 计算 cnts 的后缀和\n",
    "        for i in range(len(cnts) - 1, 0, -1):\n",
    "            cnts[i - 1] += cnts[i]\n",
    "\n",
    "        for i, q in enumerate(queries):\n",
    "            queries[i] = cnts[min(q + 1, len(cnts) - 1)]\n",
    "        return queries"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, n: int, edges: List[List[int]], queries: List[int]) -> List[int]:\n",
    "        indegree = [0]*(n+1) \n",
    "        for x,y in edges:\n",
    "            indegree[x] += 1\n",
    "            indegree[y] += 1\n",
    "        \n",
    "        g = collections.Counter(tuple(sorted(e)) for e in edges)\n",
    "        ans = [0] * len(queries)\n",
    "        sorted_deg = sorted(indegree)  # 排序，为了双指针\n",
    "        # print(indegree,sorted_deg)\n",
    "        # print(g)\n",
    "        for i,limit in enumerate(queries):\n",
    "            left = 1 \n",
    "            right = n\n",
    "            while left<right:\n",
    "                if sorted_deg[left] + sorted_deg[right] <= limit:\n",
    "                    left += 1\n",
    "                else:\n",
    "                    ans[i] += right -left\n",
    "                    right -= 1\n",
    "            for (x,y),cnt in g.items():\n",
    "                if limit<indegree[x]+indegree[y]<=limit+cnt:#必需严格大于limit,因为上面筛选的时候就是这样的\n",
    "                    ans[i] -= 1\n",
    "        return ans\n",
    "\n",
    "\n",
    "\n",
    "        \n",
    "\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "        # deg[i] 表示与点 i 相连的边的数目\n",
    "        # deg = [0] * (n + 1)  # 节点编号从 1 到 n\n",
    "        # for x, y in edges:\n",
    "        #     deg[x] += 1\n",
    "        #     deg[y] += 1\n",
    "        # # 统计每条边的出现次数，注意 1-2 和 2-1 算同一条边\n",
    "        # cnt_e = Counter(tuple(sorted(e)) for e in edges)\n",
    "\n",
    "        # ans = [0] * len(queries)\n",
    "        # sorted_deg = sorted(deg)  # 排序，为了双指针\n",
    "        # print(deg,sorted_deg)\n",
    "        # for j, q in enumerate(queries):\n",
    "        #     left, right = 1, n  # 相向双指针\n",
    "        #     while left < right:\n",
    "        #         if sorted_deg[left] + sorted_deg[right] <= q:\n",
    "        #             left += 1\n",
    "        #         else:\n",
    "        #             ans[j] += right - left\n",
    "        #             right -= 1\n",
    "                    \n",
    "        #     for (x, y), c in cnt_e.items():\n",
    "        #         if q < deg[x] + deg[y] <= q + c:\n",
    "        #             ans[j] -= 1\n",
    "        # return ans\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, n: int, edges: List[List[int]], queries: List[int]) -> List[int]:\n",
    "        # deg[i] 表示与点 i 相连的边的数目\n",
    "        deg = [0] * (n + 1)  # 节点编号从 1 到 n\n",
    "        for x, y in edges:\n",
    "            deg[x] += 1\n",
    "            deg[y] += 1\n",
    "        # 统计每条边的出现次数，注意 1-2 和 2-1 算同一条边\n",
    "        cnt_e = Counter(tuple(sorted(e)) for e in edges)\n",
    "\n",
    "        ans = [0] * len(queries)\n",
    "        sorted_deg = sorted(deg)  # 排序，为了双指针\n",
    "        for j, q in enumerate(queries):\n",
    "            left, right = 1, n  # 相向双指针\n",
    "            while left < right:\n",
    "                if sorted_deg[left] + sorted_deg[right] <= q:\n",
    "                    left += 1\n",
    "                else:\n",
    "                    ans[j] += right - left\n",
    "                    right -= 1\n",
    "            for (x, y), c in cnt_e.items():\n",
    "                if q < deg[x] + deg[y] <= q + c:\n",
    "                    ans[j] -= 1\n",
    "        return ans\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, n: int, edges: List[List[int]], queries: List[int]) -> List[int]:\n",
    "        # deg[i] 表示与点 i 相连的边的数目\n",
    "        deg = [0] * (n + 1)  # 节点编号从 1 到 n\n",
    "        for x, y in edges:\n",
    "            deg[x] += 1\n",
    "            deg[y] += 1\n",
    "        # 统计每条边的出现次数，注意 1-2 和 2-1 算同一条边\n",
    "        cnt_e = Counter(tuple(sorted(e)) for e in edges)\n",
    "\n",
    "        ans = [0] * len(queries)\n",
    "        sorted_deg = sorted(deg)  # 排序，为了双指针\n",
    "        for j, q in enumerate(queries):\n",
    "            left, right = 1, n  # 相向双指针\n",
    "            while left < right:\n",
    "                if sorted_deg[left] + sorted_deg[right] <= q:\n",
    "                    left += 1\n",
    "                else:\n",
    "                    ans[j] += right - left\n",
    "                    right -= 1\n",
    "            for (x, y), c in cnt_e.items():\n",
    "                if q < deg[x] + deg[y] <= q + c:\n",
    "                    ans[j] -= 1\n",
    "        return ans\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, n: int, edges: List[List[int]], queries: List[int]) -> List[int]:\n",
    "        degree = [0 for _ in range(n+1)]\n",
    "        cnt = Counter(tuple(sorted(e)) for e in edges)\n",
    "        for e in edges:\n",
    "            degree[e[0]] += 1\n",
    "            degree[e[1]] += 1\n",
    "\n",
    "        sorted_degree = sorted(degree)\n",
    "        \n",
    "        ans = []\n",
    "        for i,d in enumerate(queries):\n",
    "            total = 0\n",
    "            left = 1\n",
    "            right = n\n",
    "            while left<right:\n",
    "                if sorted_degree[left] + sorted_degree[right] <= d:\n",
    "                    left += 1\n",
    "                else:\n",
    "                    total += right - left\n",
    "                    right -= 1\n",
    "            \n",
    "            for (x,y),c in cnt.items():\n",
    "                if degree[x] + degree[y] > d and degree[x] + degree[y] - c <= d:\n",
    "                    total -= 1\n",
    "\n",
    "            ans.append(total)\n",
    "        return ans\n",
    "\n",
    "            "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, n: int, edges: List[List[int]], queries: List[int]) -> List[int]:\n",
    "        res = [0] * len(queries)\n",
    "        cnt = [0] * n\n",
    "        e = dict()\n",
    "        nn = 0\n",
    "        for y in edges:\n",
    "            cnt[y[0]-1] += 1\n",
    "            cnt[y[1]-1] += 1\n",
    "            mi, ma = min(y[0], y[1]) - 1, max(y[0], y[1]) - 1\n",
    "            e.setdefault(mi, dict())\n",
    "            e[mi].setdefault(ma, 0)\n",
    "            e[mi][ma] += 1\n",
    "        z = sorted(cnt)\n",
    "        nn = len(z)\n",
    "        dd = dict()\n",
    "        cc = Counter(cnt)\n",
    "        @lru_cache(n)\n",
    "        def findy(jj, i):\n",
    "            if jj > queries[i]:\n",
    "                return n - 1\n",
    "            yy = bisect_right(z, queries[i] - jj)\n",
    "            return nn - yy - (2 * jj > queries[i])\n",
    "        for i in range(len(queries)):\n",
    "            if i in dd:\n",
    "                res[i] = dd[i]\n",
    "                continue\n",
    "            for j, ccc in cc.items():\n",
    "                res[i] += findy(j, i) * ccc\n",
    "            for u, vv in e.items():\n",
    "                for edg, v in vv.items():\n",
    "                    if queries[i] < cnt[edg] + cnt[u] <= v + queries[i]:\n",
    "                        res[i] -= 2\n",
    "            res[i] = res[i]// 2\n",
    "            dd[i] = res[i]\n",
    "        \n",
    "        return res\n",
    "\n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, n: int, edges: List[List[int]], queries: List[int]) -> List[int]:\n",
    "        res = [0] * len(queries)\n",
    "        cnt = [0] * n\n",
    "        e = dict()\n",
    "        nn = 0\n",
    "        for y in edges:\n",
    "            cnt[y[0]-1] += 1\n",
    "            cnt[y[1]-1] += 1\n",
    "            mi, ma = min(y[0], y[1]) - 1, max(y[0], y[1]) - 1\n",
    "            e.setdefault(mi, dict())\n",
    "            e[mi].setdefault(ma, 0)\n",
    "            e[mi][ma] += 1\n",
    "        z = sorted(cnt)\n",
    "        nn = len(z)\n",
    "        dd = dict()\n",
    "        @lru_cache(n)\n",
    "        def findy(jj, i):\n",
    "            if jj > queries[i]:\n",
    "                return n - 1\n",
    "            yy = bisect_right(z, queries[i] - jj)\n",
    "            return nn - yy - (2 * jj > queries[i])\n",
    "        for i in range(len(queries)):\n",
    "            if i in dd:\n",
    "                res[i] = dd[i]\n",
    "                continue\n",
    "            for j in cnt:\n",
    "                res[i] += findy(j, i)\n",
    "            for u, vv in e.items():\n",
    "                for edg, v in vv.items():\n",
    "                    if queries[i] < cnt[edg] + cnt[u] <= v + queries[i]:\n",
    "                        res[i] -= 2\n",
    "            y = findy(0, i)\n",
    "            res[i] += y * (n - nn)\n",
    "            res[i] = res[i]// 2\n",
    "            dd[i] = res[i]\n",
    "        \n",
    "        return res\n",
    "\n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, n: int, edges: List[List[int]], queries: List[int]) -> List[int]:\n",
    "        \"\"\"\n",
    "        # 枚举O(n log(n) + len(queries)(n+len(edges)))\n",
    "        deg = [0] * (n+1)  # 记录点的邻边数\n",
    "        for x, y in edges:\n",
    "            deg[x] += 1\n",
    "            deg[y] += 1\n",
    "        sorted_deg = sorted(deg)  # 排序后的点邻边数，有一个点0实际不存在需跳过\n",
    "        count_edge = Counter(tuple(sorted(e)) for e in edges)  # 记录各边数\n",
    "\n",
    "        ans = [0] * len(queries)\n",
    "        for i, q in enumerate(queries):\n",
    "            left, right = 1, n\n",
    "            while left < right:\n",
    "                if sorted_deg[left] + sorted_deg[right] <= q:\n",
    "                    left += 1\n",
    "                else:\n",
    "                    ans[i] += right - left\n",
    "                    right -= 1\n",
    "            \n",
    "            for (x, y), c in count_edge.items():\n",
    "                if deg[x] + deg[y] > q and deg[x] + deg[y] - c <= q:\n",
    "                    ans[i] -= 1\n",
    "        return ans\n",
    "        \"\"\"\n",
    "        # 终极优化O(n+len(queries)+len(edges))\n",
    "        # 2m个积木只能搭建约(4m)^(0.5)个不同高度的塔\n",
    "        # 重复计算很多，q里面的值可能一样，可以计算cnt=1, 2, ...的数量，最后后缀和\n",
    "        deg = [0] * (n+1)  # 记录点的邻边数\n",
    "        count_edge = {}  # 记录各边数,{(x, y)出现在edges中的边，x<y: c边数}\n",
    "        for x, y in edges:\n",
    "            if x > y:\n",
    "                x, y = y, x\n",
    "            deg[x] += 1\n",
    "            deg[y] += 1\n",
    "            count_edge[(x, y)] = count_edge.get((x, y), 0) + 1  # 统计edges中各边数量\n",
    "\n",
    "        count_deg = Counter(deg[1:])  # 各邻边数量的点数{邻边数: 对应的点数}\n",
    "        cnt = [0] * (2*max(count_deg) + 2)  # 邻边数为索引的点对数量\n",
    "        for deg1, c_p1 in count_deg.items():\n",
    "            for deg2, c_p2 in count_deg.items():\n",
    "                if deg1 < deg2:  # 避免重复计算\n",
    "                    cnt[deg1+deg2] += c_p1 * c_p2\n",
    "                elif deg1 == deg2:\n",
    "                    cnt[deg1+deg2] += c_p1 * (c_p1-1) // 2  # 点对的两点有重复未去除情况\n",
    "        \n",
    "        for (x, y), c in count_edge.items():  # 点对去重\n",
    "            tmp = deg[x] + deg[y]\n",
    "            cnt[tmp] -= 1\n",
    "            cnt[tmp-c] += 1\n",
    "\n",
    "        for i in range(len(cnt)-2, -1, -1):\n",
    "            cnt[i] += cnt[i+1]\n",
    "\n",
    "        for i, q in enumerate(queries):\n",
    "            queries[i] = cnt[min(q+1, len(cnt)-1)]\n",
    "            print(queries)\n",
    "        return queries\n",
    "\n",
    "\n",
    "\n",
    "        \n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "\n",
    "class Solution:\n",
    "\n",
    "    def encode(self, a: int, b: int, n: int):\n",
    "        return max(a, b) * (n + 1) + min(a, b)\n",
    "    def countPairs(self, n: int, edges: List[List[int]], queries: List[int]) -> List[int]:\n",
    "\n",
    "        deg = [0] * (n + 1)\n",
    "        overlap = {}\n",
    "        distinctEdges = []\n",
    "        for i in range(edges.__len__()):\n",
    "            x = edges[i][0]\n",
    "            y = edges[i][1]\n",
    "            \n",
    "            deg[x] += 1\n",
    "            deg[y] += 1\n",
    "            idx = self.encode(x, y, n)\n",
    "            if idx not in overlap.keys():\n",
    "                distinctEdges.append((x, y))\n",
    "                overlap[idx] = 0\n",
    "            overlap[idx] += 1\n",
    "        \n",
    "        sortDeg = deg.copy()\n",
    "        sortDeg = sortDeg[1:sortDeg.__len__()]\n",
    "        sortDeg.sort()\n",
    "        \n",
    "        res = []\n",
    "        for i in range(queries.__len__()):\n",
    "            l = 0\n",
    "            r = n - 1\n",
    "            cnt = 0\n",
    "            while l < n:\n",
    "                while r > l and sortDeg[l] + sortDeg[r] > queries[i]:\n",
    "                    r -= 1\n",
    "                cnt += (n - max(l, r) - 1)\n",
    "                l += 1          \n",
    "            for j in range(distinctEdges.__len__()):\n",
    "                x = distinctEdges[j][0]\n",
    "                y = distinctEdges[j][1]\n",
    "                idx = self.encode(x, y, n)\n",
    "                if deg[x] + deg[y] > queries[i] and deg[x] + deg[y] - overlap[idx] <= queries[i]:\n",
    "                    cnt -= 1\n",
    "            res.append(cnt)\n",
    "        return res"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, n: int, edges: List[List[int]], queries: List[int]) -> List[int]:\n",
    "        res = [0] * len(queries)\n",
    "        cnt = dict()\n",
    "        e = dict()\n",
    "        for y in edges:\n",
    "            cnt.setdefault(y[0]-1, 0)\n",
    "            cnt.setdefault(y[1]-1, 0)\n",
    "            cnt[y[0]-1] += 1\n",
    "            cnt[y[1]-1] += 1\n",
    "            mi, ma = min(y[0], y[1]) - 1, max(y[0], y[1]) - 1\n",
    "            e.setdefault(mi, dict())\n",
    "            e[mi].setdefault(ma, 0)\n",
    "            e[mi][ma] += 1\n",
    "        z = sorted(cnt.values())\n",
    "        dd = dict()\n",
    "        @lru_cache(n)\n",
    "        def findy(yyy):\n",
    "            return bisect_right(z, yyy)\n",
    "        for i in range(len(queries)):\n",
    "            if i in dd:\n",
    "                res[i] = dd[i]\n",
    "                continue\n",
    "            for x, j in cnt.items():\n",
    "                if j > queries[i]:\n",
    "                    res[i] += n - 1\n",
    "                    continue\n",
    "                y = findy(queries[i] - j)\n",
    "                res[i] += len(z) - y - (2 * j > queries[i])\n",
    "                for edg in e.get(x, dict()):\n",
    "                    if cnt[edg] + j - e[x][edg] <= queries[i] and cnt[edg] + j > queries[i]:\n",
    "                        res[i] -= 2\n",
    "            y = len(z) - findy(queries[i])\n",
    "            res[i] += y * (n - len(z))\n",
    "            res[i] = res[i]// 2\n",
    "            dd[i] = res[i]\n",
    "        \n",
    "        return res\n",
    "\n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, n: int, edges: List[List[int]], queries: List[int]) -> List[int]:\n",
    "        d = Counter()\n",
    "        e = {i:defaultdict(int) for i in range(1,n+1)}\n",
    "        for u,v in edges:\n",
    "            d[u]+=1\n",
    "            d[v]+=1\n",
    "            e[min(u,v)][max(u,v)]+=1\n",
    "        ans = []\n",
    "        for q in queries:\n",
    "            cnt = 0\n",
    "            blist = [d[n]]\n",
    "            for i in range(n-1,0,-1):\n",
    "                if q+1-d[i]<=0:\n",
    "                    cnt += len(blist)\n",
    "                else:\n",
    "                    j = bisect_left(blist,q+1-d[i])\n",
    "                    cnt += (len(blist) - j)\n",
    "                    for b in e[i]:\n",
    "                        if d[i]+d[b]>=q+1 and d[i]+d[b]-e[i][b]<q+1:\n",
    "                            cnt-=1\n",
    "                insort(blist,d[i])\n",
    "            ans.append(cnt)\n",
    "        return ans"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, n: int, edges: List[List[int]], queries: List[int]) -> List[int]:\n",
    "        res = [0] * len(queries)\n",
    "        cnt = dict()\n",
    "        e = dict()\n",
    "        nn = 0\n",
    "        for y in edges:\n",
    "            cnt.setdefault(y[0]-1, 0)\n",
    "            cnt.setdefault(y[1]-1, 0)\n",
    "            cnt[y[0]-1] += 1\n",
    "            cnt[y[1]-1] += 1\n",
    "            mi, ma = min(y[0], y[1]) - 1, max(y[0], y[1]) - 1\n",
    "            e.setdefault(mi, dict())\n",
    "            e[mi].setdefault(ma, 0)\n",
    "            e[mi][ma] += 1\n",
    "        z = sorted(cnt.values())\n",
    "        nn = len(z)\n",
    "        dd = dict()\n",
    "        @lru_cache(n)\n",
    "        def findy(jj, i):\n",
    "            if jj > queries[i]:\n",
    "                return n - 1\n",
    "            yy = bisect_right(z, queries[i] - jj)\n",
    "            return nn - yy - (2 * jj > queries[i])\n",
    "        for i in range(len(queries)):\n",
    "            if i in dd:\n",
    "                res[i] = dd[i]\n",
    "                continue\n",
    "            for j in cnt.values():\n",
    "                res[i] += findy(j, i)\n",
    "            for u, vv in e.items():\n",
    "                for edg, v in vv.items():\n",
    "                    if queries[i] < cnt[edg] + cnt[u] <= v + queries[i]:\n",
    "                        res[i] -= 2\n",
    "            y = findy(0, i)\n",
    "            res[i] += y * (n - nn)\n",
    "            res[i] = res[i]// 2\n",
    "            dd[i] = res[i]\n",
    "        \n",
    "        return res\n",
    "\n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, n: int, edges: List[List[int]], queries: List[int]) -> List[int]:\n",
    "        dic=defaultdict(int)\n",
    "        degree={i:0 for i in range(1,n+1)}\n",
    "        for i in edges:\n",
    "            \n",
    "            a,b=i[0],i[1]\n",
    "            degree[a]+=1\n",
    "            degree[b]+=1\n",
    "            a,b=min(a,b),max(a,b)\n",
    "            dic[(a,b)]+=1\n",
    "        items=sorted(degree.items(),key=lambda x:(x[1],x[0]))\n",
    "        keys=[i[0] for i in items]\n",
    "        values=[i[1] for i in items]\n",
    "        res=[]\n",
    "        for i in queries:\n",
    "            total=0\n",
    "            for j in range(len(values)):\n",
    "                cur=values[j]\n",
    "                b=max(j+1,bisect_right(values,i-cur))\n",
    "                total+=n-b\n",
    "            for j in dic:\n",
    "                if degree[j[0]]+degree[j[1]]>i and degree[j[0]]+degree[j[1]]-dic[j]<=i:\n",
    "                    total-=1\n",
    "            res.append(total)\n",
    "        return res\n",
    "            "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, n: int, edges: List[List[int]], queries: List[int]) -> List[int]:\n",
    "        deg = [0] * n\n",
    "        edgeCnt = collections.Counter()\n",
    "        for a, b in edges:\n",
    "            if a > b:\n",
    "                a, b = b, a\n",
    "            deg[a - 1] += 1\n",
    "            deg[b - 1] += 1\n",
    "            edgeCnt[a - 1, b - 1] += 1\n",
    "        degSort = sorted(deg)\n",
    "        m = len(queries)\n",
    "        res = [0] * m\n",
    "        for i, q in enumerate(queries):\n",
    "            cnt = 0\n",
    "            left, right = 0, n - 1\n",
    "            while left < right:\n",
    "                if degSort[left] + degSort[right] <= q:\n",
    "                    left += 1\n",
    "                else:\n",
    "                    cnt += right - left\n",
    "                    right -= 1\n",
    "            for a, b in edgeCnt:\n",
    "                if deg[a] + deg[b] > q and deg[a] + deg[b] - edgeCnt[a, b] <= q:\n",
    "                    cnt -= 1\n",
    "            res[i] = cnt\n",
    "        return res"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, n: int, edges: List[List[int]], queries: List[int]) -> List[int]:\n",
    "        res = [0] * len(queries)\n",
    "        cnt = dict()\n",
    "        e = dict()\n",
    "        for y in edges:\n",
    "            cnt.setdefault(y[0]-1, 0)\n",
    "            cnt.setdefault(y[1]-1, 0)\n",
    "            cnt[y[0]-1] += 1\n",
    "            cnt[y[1]-1] += 1\n",
    "            mi, ma = min(y[0], y[1]) - 1, max(y[0], y[1]) - 1\n",
    "            e.setdefault(mi, dict())\n",
    "            e[mi].setdefault(ma, 0)\n",
    "            e[mi][ma] += 1\n",
    "        z = sorted(cnt.values())\n",
    "        dd = dict()\n",
    "        @lru_cache(n)\n",
    "        def findy(yyy):\n",
    "            return bisect_right(z, yyy)\n",
    "        for i in range(len(queries)):\n",
    "            if i in dd:\n",
    "                res[i] = dd[i]\n",
    "                continue\n",
    "            for x, j in cnt.items():\n",
    "                if j > queries[i]:\n",
    "                    res[i] += n - 1\n",
    "                    continue\n",
    "                y = findy(queries[i] - j)\n",
    "                res[i] += len(z) - y - (2 * j > queries[i])\n",
    "            for u, vv in e.items():\n",
    "                for edg, v in vv.items():\n",
    "                    if queries[i] < cnt[edg] + cnt[u] <= v + queries[i]:\n",
    "                        res[i] -= 2\n",
    "            y = len(z) - findy(queries[i])\n",
    "            res[i] += y * (n - len(z))\n",
    "            res[i] = res[i]// 2\n",
    "            dd[i] = res[i]\n",
    "        \n",
    "        return res\n",
    "\n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, n: int, edges: List[List[int]], queries: List[int]) -> List[int]:\n",
    "        d = defaultdict(set)\n",
    "        res = [0] * len(queries)\n",
    "        cnt = [0] * n\n",
    "        e = dict()\n",
    "        for y in edges:\n",
    "            cnt[y[0]-1] += 1\n",
    "            cnt[y[1]-1] += 1\n",
    "            e.setdefault(y[0]-1, dict())\n",
    "            e.setdefault(y[1]-1, dict())\n",
    "            e[y[0]-1].setdefault(y[1]-1, 0)\n",
    "            e[y[1]-1].setdefault(y[0]-1, 0)\n",
    "            e[y[0]-1][y[1]-1] += 1\n",
    "            e[y[1]-1][y[0]-1] += 1\n",
    "        z = sorted(cnt)\n",
    "        for i in range(len(queries)):\n",
    "            for x, j in enumerate(cnt):\n",
    "                if j > queries[i]:\n",
    "                    res[i] += n - 1\n",
    "                    continue\n",
    "                y = bisect_right(z, queries[i] - j)\n",
    "                res[i] += len(z) - y - (2 * j > queries[i])\n",
    "                if x in e:\n",
    "                    for edg in e[x]:\n",
    "                        if cnt[edg] + j - e[x][edg] <= queries[i] and cnt[edg] + j > queries[i]:\n",
    "                            res[i] -= 1\n",
    "            res[i] = res[i]// 2\n",
    "        \n",
    "        return res\n",
    "\n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, n: int, edges: List[List[int]], queries: List[int]) -> List[int]:\n",
    "        d = defaultdict(set)\n",
    "        res = [0] * len(queries)\n",
    "        cnt = [0] * n\n",
    "        e = dict()\n",
    "        for y in edges:\n",
    "            cnt[y[0]-1] += 1\n",
    "            cnt[y[1]-1] += 1\n",
    "            e.setdefault(y[0]-1, dict())\n",
    "            e.setdefault(y[1]-1, dict())\n",
    "            e[y[0]-1].setdefault(y[1]-1, 0)\n",
    "            e[y[1]-1].setdefault(y[0]-1, 0)\n",
    "            e[y[0]-1][y[1]-1] += 1\n",
    "            e[y[1]-1][y[0]-1] += 1\n",
    "        z = sorted(cnt)\n",
    "        for i in range(len(queries)):\n",
    "            for x, j in enumerate(cnt):\n",
    "                if j > queries[i]:\n",
    "                    res[i] += n - 1\n",
    "                    continue\n",
    "                y = bisect_right(z, queries[i] - j)\n",
    "                res[i] += len(z) - y - (2 * j > queries[i])\n",
    "                for edg in e.get(x, dict()):\n",
    "                    if cnt[edg] + j - e[x][edg] <= queries[i] and cnt[edg] + j > queries[i]:\n",
    "                        res[i] -= 1\n",
    "            res[i] = res[i]// 2\n",
    "        \n",
    "        return res\n",
    "\n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, n: int, edges: List[List[int]], queries: List[int]) -> List[int]:\n",
    "\n",
    "        # 统计每个点的连接数量&相互连接数量：O(E)\n",
    "        count_num = [0] * n\n",
    "        count_cross = collections.defaultdict(collections.Counter)\n",
    "        for u, v in edges:\n",
    "            count_num[u - 1] += 1\n",
    "            count_num[v - 1] += 1\n",
    "            count_cross[u - 1][v - 1] += 1\n",
    "            count_cross[v - 1][u - 1] += 1\n",
    "\n",
    "        # 排序连接数量：O(NlogN)\n",
    "        sorted_num = sorted(count_num)\n",
    "\n",
    "        ans = []\n",
    "\n",
    "        for query in queries:\n",
    "            res = 0\n",
    "\n",
    "            # 统计每个结点可以选择的结点数量\n",
    "            # 每个结点都考虑除自己以外所有的边，最终得出结果的2倍\n",
    "            for i in range(n):\n",
    "                # 如果当前结点的连接的边数已经达到查询要求，则当前结点所有连接的边均符合要求\n",
    "                if count_num[i] > query:\n",
    "                    res += (n - 1)\n",
    "\n",
    "                # 如果当前结点的连接的边数未达到查询要求，则二分查找相邻的符号的点对\n",
    "                else:\n",
    "                    # 计算还需要的边数量\n",
    "                    need = query - count_num[i]\n",
    "\n",
    "                    # 二分查找符合条件的边（暂不考虑点对本身就是一条/多条边；暂不考虑将自身算在内的情况）\n",
    "                    # 单次：O(logN)；累计：O(QNlogN)\n",
    "                    idx = bisect.bisect_right(sorted_num, need)\n",
    "                    res += (n - idx)\n",
    "\n",
    "                    # 将自身剔除（如果被算进去的话）\n",
    "                    if count_num[i] > need:\n",
    "                        res -= 1\n",
    "\n",
    "                    # 处理点对本身就是一条/多条边的情况，如果不足要求则剔除\n",
    "                    # 单次：O(E/N)；累计：O(QE)\n",
    "                    for j in count_cross[i]:\n",
    "                        # 按此前方法计算被计入，但实际上不符合查询要求的情况\n",
    "                        if count_num[i] + count_num[j] > query >= count_num[i] + count_num[j] - count_cross[i][j]:\n",
    "                            res -= 1\n",
    "\n",
    "            ans.append(res // 2)\n",
    "\n",
    "        return ans\n",
    "\n",
    "\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, n: int, edges: List[List[int]], queries: List[int]) -> List[int]:\n",
    "        d = defaultdict(set)\n",
    "        res = [0] * len(queries)\n",
    "        cnt = [0] * n\n",
    "        e = dict()\n",
    "        for y in edges:\n",
    "            cnt[y[0]-1] += 1\n",
    "            cnt[y[1]-1] += 1\n",
    "            e.setdefault(y[0]-1, dict())\n",
    "            e.setdefault(y[1]-1, dict())\n",
    "            e[y[0]-1].setdefault(y[1]-1, 0)\n",
    "            e[y[1]-1].setdefault(y[0]-1, 0)\n",
    "            e[y[0]-1][y[1]-1] += 1\n",
    "            e[y[1]-1][y[0]-1] += 1\n",
    "        z = sorted(cnt)\n",
    "        for i in range(len(queries)):\n",
    "            for x, j in enumerate(cnt):\n",
    "                \n",
    "                y = bisect_right(z, queries[i] - j)\n",
    "                res[i] += len(z) - y - (2 * j > queries[i])\n",
    "                for edg in e.get(x, dict()):\n",
    "                    if cnt[edg] + j - e[x][edg] <= queries[i] and cnt[edg] + j > queries[i]:\n",
    "                        res[i] -= 1\n",
    "            res[i] = res[i]// 2\n",
    "        \n",
    "        return res\n",
    "\n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, n: int, edges: List[List[int]], queries: List[int]) -> List[int]:\n",
    "        lines = [0] * (n + 1)\n",
    "        connect = defaultdict(dict)\n",
    "        for u, v in edges:\n",
    "            lines[u] += 1\n",
    "            lines[v] += 1\n",
    "            if v not in connect[u]:\n",
    "                connect[u][v] = 0\n",
    "            connect[u][v] += 1\n",
    "            if u not in connect[v]:\n",
    "                connect[v][u] = 0\n",
    "            connect[v][u] += 1\n",
    "        # print(lines)\n",
    "        # print(connect)\n",
    "        # freq[i, j] j个点所连接边数量为i\n",
    "        freqs = defaultdict(int)\n",
    "        for i in range(1, n + 1):\n",
    "            freqs[lines[i]] += 1\n",
    "        freqs = [[k, v] for k, v in freqs.items()]\n",
    "        freqs.sort(key=lambda x: x[0])\n",
    "        # print(freqs)\n",
    "        l = len(edges)\n",
    "        # counts[i] 两个点边数之和为i\n",
    "        counts = [0] * (l + 1)\n",
    "        for i in range(len(freqs)):\n",
    "            iline, ipoints = freqs[i]\n",
    "            counts[min(iline * 2, l)] += ipoints * (ipoints - 1) // 2\n",
    "            for j in range(i + 1, len(freqs)):\n",
    "                jline, jpoints = freqs[j]\n",
    "                counts[min(iline + jline, l)] += ipoints * jpoints\n",
    "        # print(counts)\n",
    "        # 根据uv之间的边修正\n",
    "        for u, f in connect.items():\n",
    "            for v, c in f.items():\n",
    "                if u < v:\n",
    "                    counts[min(lines[u] + lines[v], l)] -= 1\n",
    "                    counts[min(lines[u] + lines[v] - c, l)] += 1\n",
    "        # print(counts)\n",
    "        for i in range(l - 1, -1, -1):\n",
    "            counts[i] += counts[i + 1]\n",
    "        # print(counts)\n",
    "        \n",
    "        return [counts[q + 1] for q in queries]\n",
    "        \n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, n: int, edges: List[List[int]], queries: List[int]) -> List[int]:\n",
    "        deg = {}\n",
    "        E = set()\n",
    "        for i in range(n+1):\n",
    "            deg[i] = 0\n",
    "        overlap = {}\n",
    "        ans = []\n",
    "\n",
    "        for e in edges:\n",
    "            sortede = tuple(sorted(e))\n",
    "            deg[sortede[0]] += 1\n",
    "            deg[sortede[1]] += 1\n",
    "            overlap[sortede] = overlap.get(sortede, 0) + 1\n",
    "            E.add(sortede)\n",
    "        \n",
    "        tmpdeg = deepcopy(deg)\n",
    "        deg = deg.items()\n",
    "        deg = sorted(deg, key = lambda x: x[1])\n",
    "        #print(deg)\n",
    "        #Double Pointer\n",
    "\n",
    "        for q in queries:\n",
    "            count = 0\n",
    "            l, r = 1, n\n",
    "\n",
    "            while l < r:\n",
    "                degsum = deg[l][1] + deg[r][1]\n",
    "                #print(l, r, degsum)\n",
    "                if degsum > q:\n",
    "                    count += (r - l)\n",
    "                    r -= 1\n",
    "                else:\n",
    "                    l += 1\n",
    "            #print(count)\n",
    "\n",
    "            for edge in E:\n",
    "                sumdeg = tmpdeg[edge[0]] + tmpdeg[edge[1]]\n",
    "                #print(sumdeg, \"sumdeg\", edge)\n",
    "                if sumdeg > q and sumdeg - overlap[edge] <= q:\n",
    "                    #print(edge, overlap[edge], sumdeg)\n",
    "                    count -= 1\n",
    "                    \n",
    "            ans.append(count)\n",
    "\n",
    "        return ans"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, n: int, edges: List[List[int]], queries: List[int]) -> List[int]:\n",
    "        # edges = [[1,5],[1,5],[3,4],[2,5],[1,3],[5,1],[2,3],[2,5]]\n",
    "        # n = 5\n",
    "        # queries = [5]\n",
    "        from sortedcontainers import SortedList\n",
    "        aEdge = defaultdict(list)\n",
    "        adj = Counter()\n",
    "        edgeCounter = Counter()\n",
    "        for u, v in edges:\n",
    "            if u > v:\n",
    "                u, v = v, u\n",
    "            adj[u] += 1\n",
    "            adj[v] += 1\n",
    "            if (u, v) not in edgeCounter:\n",
    "                aEdge[v].append(u)\n",
    "            edgeCounter[(u, v)] += 1\n",
    "        # print(aEdge, adj, edgeCounter)\n",
    "        ret = []\n",
    "        for query in queries:\n",
    "            ans = 0\n",
    "            prev = SortedList()\n",
    "            for u in range(1, n + 1):\n",
    "                ans += prev.bisect_right(adj[u]) - len([v for v in aEdge[u] if query < adj[v] + adj[u] <= query + edgeCounter[(v, u)]])\n",
    "                prev.add(query - adj[u] + 1)\n",
    "                # print(ans, prev, u)\n",
    "            ret.append(ans)\n",
    "        return ret"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, n: int, edges: List[List[int]], queries: List[int]) -> List[int]:\n",
    "        degrees = [0] * (n + 1)\n",
    "        d = {}\n",
    "        for u, v in edges:\n",
    "            degrees[u] += 1\n",
    "            degrees[v] += 1\n",
    "            if u not in d:\n",
    "                d[u] = {}\n",
    "            d[u][v] = d[u].get(v, 0) + 1\n",
    "            if v not in d:\n",
    "                d[v] = {}\n",
    "            d[v][u] = d[v].get(u, 0) + 1\n",
    "        sorted_degrees = sorted(degrees[1:])\n",
    "        import bisect\n",
    "        res = []\n",
    "        for limit in queries:\n",
    "            cnt = 0\n",
    "            for i in range(1, n + 1):\n",
    "                cnt += n - bisect.bisect_left(sorted_degrees, limit - degrees[i] + 1)\n",
    "                if degrees[i] * 2 > limit:\n",
    "                    cnt -= 1\n",
    "            cnt = cnt // 2\n",
    "            for i in d:\n",
    "                for j in d[i]:\n",
    "                    if i < j and degrees[i] + degrees[j] > limit and degrees[i] + degrees[j] - d[i][j] <= limit:\n",
    "                        cnt -= 1\n",
    "            res.append(cnt)\n",
    "        return res"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, n: int, edges: List[List[int]], queries: List[int]) -> List[int]:\n",
    "        adj = defaultdict(partial(defaultdict, int))\n",
    "        for u, v in edges :\n",
    "            adj[u][v] += 1\n",
    "            adj[v][u] += 1\n",
    "        Vcnt = [0 for i in range(n + 1)]\n",
    "        for k, v in adj.items() :\n",
    "            Vcnt[k] = sum(v.values())\n",
    "\n",
    "        degree = sorted(Vcnt)\n",
    "        res = []\n",
    "        \n",
    "        for querie in queries :\n",
    "            tmp = 0\n",
    "            for i, left in enumerate(degree[1:], 1) :\n",
    "                j = bisect.bisect(degree, querie - left, i + 1)\n",
    "                tmp += n - j + 1\n",
    "            for i,cnt in adj.items() :\n",
    "                for j, c in cnt.items() :\n",
    "                    if i < j and Vcnt[i] + Vcnt[j] > querie and Vcnt[i] + Vcnt[j] - c <= querie :\n",
    "                        tmp -= 1\n",
    "            res.append(tmp)\n",
    "        return res   \n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, n: int, edges: List[List[int]], queries: List[int]) -> List[int]:\n",
    "        nums = [Counter() for _ in range(n)]\n",
    "        size = [0]*n\n",
    "        for i,j in edges:\n",
    "            i -= 1;j -= 1\n",
    "            nums[i][j] += 1;nums[j][i] += 1\n",
    "            size[i] += 1;size[j] += 1\n",
    "        mx = size[:]\n",
    "        size.sort()\n",
    "        ans = [0]*(len(queries))\n",
    "        for i in range(n):\n",
    "            lin = []\n",
    "            for j in nums[i]:\n",
    "                lin.append((mx[j],mx[j]-nums[i][j]))\n",
    "            lin.sort()\n",
    "            m = mx[i]\n",
    "            for j in range(len(queries)):\n",
    "                q = queries[j]\n",
    "                bi = bisect.bisect_right(size,q-m)\n",
    "                ans[j] += n-bi if m <= q-m else n-bi-1\n",
    "                for k in range(len(lin)-1,-1,-1):\n",
    "                    if lin[k][0] <= q-m:break\n",
    "                    if lin[k][1] <= q-m:ans[j] -= 1\n",
    "        return [x//2 for x in ans]\n",
    "\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, n: int, edges: List[List[int]], queries: List[int]) -> List[int]:\n",
    "        de = [0] * (n + 1)\n",
    "        s = defaultdict(Counter)\n",
    "        for x, y in edges:\n",
    "            de[x] += 1\n",
    "            de[y] += 1\n",
    "            # s[tuple(sorted(x, y))] += 1\n",
    "            s[x][y] += 1\n",
    "            s[y][x] += 1\n",
    "        arr = []\n",
    "        for i, v in enumerate(de):\n",
    "            if i == 0:\n",
    "                continue\n",
    "            arr.append((v, i))\n",
    "        arr.sort()\n",
    "        # print(arr, s)\n",
    "        ans = []\n",
    "        for q in queries:\n",
    "            a = 0\n",
    "            for ii, (v, i) in enumerate(arr):\n",
    "                idx = bisect.bisect(arr, (q - v + 1, 0))\n",
    "                a += n - idx\n",
    "                if idx <= ii:\n",
    "                    a -= 1\n",
    "                # print(v, i, idx, n - idx,q, a)\n",
    "                for k in s[i]:\n",
    "                    if de[k] >= q - v + 1:\n",
    "                        if v + de[k] - s[i][k] <= q:\n",
    "                            a -= 1\n",
    "                            # print(i, de[k], s[i][k], k)\n",
    "            ans.append(a // 2)\n",
    "        return ans\n",
    "\n",
    "\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, n: int, edges: List[List[int]], queries: List[int]) -> List[int]:\n",
    "        \n",
    "        c = collections.Counter()\n",
    "        d = collections.Counter()\n",
    "        for x, y in edges:\n",
    "            c[x - 1] += 1\n",
    "            c[y - 1] += 1\n",
    "            x, y = min(x, y), max(x, y)\n",
    "            d[(x - 1, y - 1)] += 1\n",
    "        a = [c[x] for x in range(n)]\n",
    "        a.sort()\n",
    "        ret = [0] * len(queries)\n",
    "        for i in range(n):\n",
    "            for j in range(len(queries)):\n",
    "                t = queries[j] + 1 - c[i]\n",
    "                p = bisect.bisect_left(a, t)\n",
    "                ret[j] += n - p\n",
    "                if t <= c[i]:\n",
    "                    ret[j] -= 1\n",
    "        for j in range(len(queries)):\n",
    "            ret[j] //= 2\n",
    "        for x, y in d:\n",
    "            for j in range(len(queries)):\n",
    "                if c[x] + c[y] > queries[j] >= c[x] + c[y] - d[(x, y)]:\n",
    "                    ret[j] -= 1\n",
    "        return ret\n",
    " "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, n: int, edges: List[List[int]], queries: List[int]) -> List[int]:\n",
    "        c = collections.Counter()\n",
    "        d = collections.Counter()\n",
    "        for x, y in edges:\n",
    "            c[x - 1] += 1\n",
    "            c[y - 1] += 1\n",
    "            x, y = min(x, y), max(x, y)\n",
    "            d[(x - 1, y - 1)] += 1\n",
    "        a = [c[x] for x in range(n)]\n",
    "        a.sort()\n",
    "        ret = [0] * len(queries)\n",
    "        for i in range(n):\n",
    "            for j in range(len(queries)):\n",
    "                t = queries[j] + 1 - c[i]\n",
    "                p = bisect.bisect_left(a, t)\n",
    "                ret[j] += n - p\n",
    "                if t <= c[i]:\n",
    "                    ret[j] -= 1\n",
    "        for j in range(len(queries)):\n",
    "            ret[j] //= 2\n",
    "        for x, y in d:\n",
    "            for j in range(len(queries)):\n",
    "                if c[x] + c[y] > queries[j] >= c[x] + c[y] - d[(x, y)]:\n",
    "                    ret[j] -= 1\n",
    "        return ret"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, n: int, edges: List[List[int]], queries: List[int]) -> List[int]:\n",
    "        deg = [0] * (n + 1)\n",
    "        \n",
    "        nEdges = len(edges)\n",
    "        overlap = defaultdict(int)\n",
    "        distinctEdges = []\n",
    "        \n",
    "        def encode(a, b, n):\n",
    "            return max(a, b) * (n + 1) + min(a, b)\n",
    "        \n",
    "        for i in range(nEdges):\n",
    "            p, q = edges[i]\n",
    "            deg[p] += 1\n",
    "            deg[q] += 1\n",
    "            idx = encode(p, q, n)\n",
    "            if overlap[idx] == 0:\n",
    "                distinctEdges.append([p, q])\n",
    "            overlap[idx] += 1\n",
    "\n",
    "        sortedDeg = sorted(deg[1:])\n",
    "        \n",
    "        nQueries = len(queries)\n",
    "        ret = [0] * nQueries\n",
    "        for i in range(nQueries):\n",
    "            l, r = 0, n - 1\n",
    "            cnt = 0\n",
    "            while l < n:\n",
    "                while r > l and sortedDeg[l] + sortedDeg[r] > queries[i]:\n",
    "                    r -= 1\n",
    "                cnt += (n - max(l, r) - 1)\n",
    "                l += 1\n",
    "\n",
    "            for j in range(len(distinctEdges)):\n",
    "                p, q = distinctEdges[j]\n",
    "                idx = encode(p, q, n)\n",
    "                if deg[p] + deg[q] > queries[i] and deg[p] + deg[q] - overlap[idx] <= queries[i]:\n",
    "                    cnt -= 1\n",
    "            ret[i] = cnt\n",
    "        \n",
    "        return ret"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, n: int, edges: List[List[int]], queries: List[int]) -> List[int]:\n",
    "        deg = [0] * (n + 1)\n",
    "        nEdges = len(edges)\n",
    "        overlap = defaultdict(int)\n",
    "        distinctEdges = []\n",
    "        def encode(a, b, n):\n",
    "            return max(a, b) * (n + 1) + min(a, b)\n",
    "\n",
    "        for i in range(nEdges):\n",
    "            p, q = edges[i]\n",
    "            deg[p] += 1\n",
    "            deg[q] += 1\n",
    "            idx = encode(p, q, n)\n",
    "            if overlap[idx] == 0:\n",
    "                distinctEdges.append([p, q])\n",
    "            overlap[idx] += 1\n",
    "\n",
    "        sortedDeg = sorted(deg[1:])\n",
    "        nQueries = len(queries)\n",
    "        ret = [0] * nQueries\n",
    "        for i in range(nQueries):\n",
    "            l, r = 0, n - 1\n",
    "            cnt = 0\n",
    "            while l < n:\n",
    "                while r > l and sortedDeg[l] + sortedDeg[r] > queries[i]:\n",
    "                    r -= 1\n",
    "                cnt += (n - max(l, r) - 1)\n",
    "                l += 1\n",
    "\n",
    "            for j in range(len(distinctEdges)):\n",
    "                p, q = distinctEdges[j]\n",
    "                idx = encode(p, q, n)\n",
    "                if deg[p] + deg[q] > queries[i] and deg[p] + deg[q] - overlap[idx] <= queries[i]:\n",
    "                    cnt -= 1\n",
    "            ret[i] = cnt\n",
    "        return ret"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, n: int, edges: List[List[int]], queries: List[int]) -> List[int]:\n",
    "        def f(x,y):return x*n+y if x < y else y*n+x\n",
    "        has = Counter()\n",
    "        nums = [[] for _ in range(n)]\n",
    "        size = [0]*n\n",
    "        for i,j in edges:\n",
    "            i -= 1;j -= 1\n",
    "            has[f(i,j)] += 1\n",
    "            if has[f(i,j)] == 1:\n",
    "                nums[i].append(j);nums[j].append(i)\n",
    "            size[i] += 1;size[j] += 1\n",
    "        mx = size[:]\n",
    "        size.sort()\n",
    "        ans = [0]*(len(edges))\n",
    "        qq = list(set(queries))\n",
    "        for i in range(n):\n",
    "            lin = []\n",
    "            for j in nums[i]:\n",
    "                lin.append((mx[j],mx[j]-has[f(i,j)]))\n",
    "            lin.sort()\n",
    "            m = mx[i]\n",
    "            for q in qq:\n",
    "                bi = bisect.bisect_right(size,q-m)\n",
    "                ans[q] += n-bi if m <= q-m else n-bi-1\n",
    "                for k in range(len(lin)-1,-1,-1):\n",
    "                    if lin[k][0] <= q-m:break\n",
    "                    if lin[k][1] <= q-m:ans[q] -= 1\n",
    "        return [ans[x]//2 for x in queries]\n",
    "\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, n: int, edges: List[List[int]], queries: List[int]) -> List[int]:\n",
    "        ad = [0] * n\n",
    "        neibors = [defaultdict(int) for _ in range(n)]\n",
    "        for x, y in edges:\n",
    "            x -= 1\n",
    "            y -= 1\n",
    "            ad[x] += 1\n",
    "            ad[y] += 1\n",
    "            neibors[y][x] += 1\n",
    "            neibors[x][y] += 1\n",
    "\n",
    "        s = sorted(range(n), key = lambda x: ad[x])\n",
    "        vs = [0] * n\n",
    "        for i, k in enumerate(s):\n",
    "            vs[k] = i\n",
    "\n",
    "        ans = [0] * len(queries)\n",
    "        for i in range(len(queries)):\n",
    "            l, r = 0, n - 1\n",
    "            while l < r:\n",
    "                while l < r and ad[s[l]] + ad[s[r]] <= queries[i]:\n",
    "                    l += 1\n",
    "                ans[i] += r - l \n",
    "                nei = neibors[s[r]]\n",
    "                for x in nei:\n",
    "                    if vs[x] > r:\n",
    "                        continue\n",
    "                    if vs[x] >= l:\n",
    "                        ans[i] -= 1\n",
    "                    if ad[s[r]] + ad[x] - nei[x] > queries[i]:\n",
    "                        ans[i] += 1\n",
    "                r -= 1\n",
    "        return ans\n",
    "                    \n",
    "\n",
    "                    \n",
    "\n",
    "                \n",
    "                 \n",
    "\n",
    "\n",
    "            \n",
    "        \n",
    "                    \n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, n: int, edges: List[List[int]], queries: List[int]) -> List[int]:\n",
    "        def f(x,y):return x*n+y if x < y else y*n+x\n",
    "        has = Counter()\n",
    "        nums = [[] for _ in range(n)]\n",
    "        size = [0]*n\n",
    "        for i,j in edges:\n",
    "            i -= 1;j -= 1\n",
    "            size[i] += 1;size[j] += 1\n",
    "            has[f(i,j)] += 1\n",
    "            if has[f(i,j)] == 1:\n",
    "                nums[i].append(j)\n",
    "                nums[j].append(i)\n",
    "        mx = size[:]\n",
    "        size.sort()\n",
    "        ans = [0]*(len(queries))\n",
    "        for m in mx:\n",
    "            for idx in range(len(queries)):\n",
    "                q = queries[idx]\n",
    "                bi = bisect.bisect_right(size,q-m)\n",
    "                ans[idx] += n-bi if m <= q-m else n-bi-1\n",
    "        for i,x in has.items():\n",
    "            i,j = i//n,i%n\n",
    "            for idx in range(len(queries)):\n",
    "                q = queries[idx]\n",
    "                if mx[i]+mx[j] > q and mx[i]+mx[j]-x <= q:\n",
    "                    ans[idx] -= 2\n",
    "        return [x//2 for x in ans]\n",
    "\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, n: int, edges: List[List[int]], queries: List[int]) -> List[int]:\n",
    "        #count = du[a]+du[b]-count[a,b]>q\n",
    "        #if count = 0, du[b]>q-du[a]\n",
    "        du = [0]*(n+1)\n",
    "        count = [{} for i in range(n+1)]\n",
    "        for a, b in edges:\n",
    "            du[a] += 1\n",
    "            du[b] += 1\n",
    "            if b in count[a]:\n",
    "                count[a][b] += 1\n",
    "            else:\n",
    "                count[a][b] = 1\n",
    "            if a in count[b]:\n",
    "                count[b][a] += 1\n",
    "            else:\n",
    "                count[b][a] = 1\n",
    "        sdu = sorted(du[1:])\n",
    "        res = []\n",
    "        for q in queries:\n",
    "            cur = 0\n",
    "            for a in range(1, n+1):\n",
    "                cur += n-bisect_right(sdu, q - du[a])\n",
    "                if du[a] > q-du[a]:\n",
    "                    cur -= 1\n",
    "                for b, v in count[a].items():\n",
    "                    if du[b] > q-du[a]:\n",
    "                        cur -= 1\n",
    "                    if du[a]+du[b]-v > q:\n",
    "                        cur += 1\n",
    "            res.append(cur//2)\n",
    "        return res"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, n: int, edges: List[List[int]], queries: List[int]) -> List[int]:\n",
    "        has = Counter()\n",
    "        nums = [Counter() for _ in range(n)]\n",
    "        size = [0]*n\n",
    "        for i,j in edges:\n",
    "            i -= 1;j -= 1\n",
    "            nums[i][j] += 1\n",
    "            nums[j][i] += 1\n",
    "            size[i] += 1;size[j] += 1\n",
    "        mx = size[:]\n",
    "        size.sort()\n",
    "        ans = [0]*(len(edges))\n",
    "        qq = list(set(queries))\n",
    "        for i in range(n):\n",
    "            lin = []\n",
    "            for j in nums[i]:\n",
    "                lin.append((mx[j],mx[j]-nums[i][j]))\n",
    "            lin.sort()\n",
    "            m = mx[i]\n",
    "            for q in qq:\n",
    "                bi = bisect.bisect_right(size,q-m)\n",
    "                ans[q] += n-bi if m <= q-m else n-bi-1\n",
    "                for k in range(len(lin)-1,-1,-1):\n",
    "                    if lin[k][0] <= q-m:break\n",
    "                    if lin[k][1] <= q-m:ans[q] -= 1\n",
    "        return [ans[x]//2 for x in queries]\n",
    "\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "\tdef countPairs(self, n, edges, queries):\n",
    "\t\tg = [defaultdict(int) for _ in range(n)]\n",
    "\t\td = [0] * n\n",
    "\t\tfor u, v in edges:\n",
    "\t\t\tg[u - 1][v - 1] += 1; g[v - 1][u - 1] += 1\n",
    "\t\t\td[u - 1] += 1; d[v - 1] += 1\n",
    "\t\to = sorted(d)\n",
    "\t\tans = [0] * len(queries)\n",
    "\t\tfor i, q in enumerate(queries):\n",
    "\t\t\tr = 0\n",
    "\t\t\tfor u in range(n):\n",
    "\t\t\t\tans[i] += n - bisect_left(o, q + 1 - d[u])\n",
    "\t\t\t\tif d[u] + d[u] >= q + 1: ans[i] -= 1\n",
    "\t\t\t\tfor v, c in g[u].items():\n",
    "\t\t\t\t\tif d[u] + d[v] > q and d[u] + d[v] - c <= q: ans[i] -= 1\n",
    "\t\t\tans[i] //= 2\n",
    "\t\treturn ans"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, n: int, edges: List[List[int]], queries: List[int]) -> List[int]:\n",
    "        num = [0] * n\n",
    "        d = [{} for i in range(n)]\n",
    "        idx = [i for i in range(n)]\n",
    "        for edge in edges:\n",
    "            a = edge[0] - 1\n",
    "            b = edge[1] - 1\n",
    "            num[a] += 1\n",
    "            num[b] += 1\n",
    "            if d[a].get(b) == None:\n",
    "                d[a][b] = 0\n",
    "            d[a][b] += 1\n",
    "            if d[b].get(a) == None:\n",
    "                d[b][a] = 0\n",
    "            d[b][a] += 1\n",
    "        idx.sort(key = lambda i : num[i])\n",
    "        ridx = [0] * n\n",
    "        for i in range(n):\n",
    "            ridx[idx[i]] = i\n",
    "        ans = []\n",
    "        for query in queries:\n",
    "            l = 0\n",
    "            nowAns = 0\n",
    "            for i in range(n - 1, -1, -1):\n",
    "                if l >= i:\n",
    "                    break\n",
    "                while l < i and num[idx[l]] + num[idx[i]] <= query:\n",
    "                    l += 1\n",
    "                nowAns += i - l\n",
    "                for k, v in d[idx[i]].items():\n",
    "                    if ridx[k] >= l and ridx[k] < i and num[k] + num[idx[i]] - v <= query:\n",
    "                        nowAns -= 1\n",
    "            ans.append(nowAns)\n",
    "        return ans"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, n: int, edges: List[List[int]], queries: List[int]) -> List[int]:\n",
    "        num = [0] * n\n",
    "        d = [{} for i in range(n)]\n",
    "        idx = [i for i in range(n)]\n",
    "        for edge in edges:\n",
    "            a = edge[0] - 1\n",
    "            b = edge[1] - 1\n",
    "            num[a] += 1\n",
    "            num[b] += 1\n",
    "            if d[a].get(b) == None:\n",
    "                d[a][b] = 0\n",
    "            d[a][b] += 1\n",
    "            if d[b].get(a) == None:\n",
    "                d[b][a] = 0\n",
    "            d[b][a] += 1\n",
    "        idx.sort(key = lambda i : num[i])\n",
    "        ridx = [0] * n\n",
    "        for i in range(n):\n",
    "            ridx[idx[i]] = i\n",
    "        ans = []\n",
    "        for query in queries:\n",
    "            l = 0\n",
    "            nowAns = 0\n",
    "            for i in range(n - 1, -1, -1):\n",
    "                if l >= i:\n",
    "                    break\n",
    "                while l < i and num[idx[l]] + num[idx[i]] <= query:\n",
    "                    l += 1\n",
    "                nowAns += i - l\n",
    "                for k, v in d[idx[i]].items():\n",
    "                    if ridx[k] >= l and ridx[k] < i and num[k] + num[idx[i]] - v <= query:\n",
    "                        nowAns -= 1\n",
    "            ans.append(nowAns)\n",
    "        return ans"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution(object):\n",
    "    def countPairs(self, n, edges, queries):\n",
    "        \"\"\"\n",
    "        :type n: int\n",
    "        :type edges: List[List[int]]\n",
    "        :type queries: List[int]\n",
    "        :rtype: List[int]\n",
    "        \"\"\"\n",
    "        dicsort=list()\n",
    "        dic=dict()\n",
    "        for edge in edges:\n",
    "            if dic.get(edge[0],None)==None:\n",
    "                dic[edge[0]]={edge[1]:1,'len':1}\n",
    "            else:\n",
    "                dic[edge[0]][edge[1]]=dic[edge[0]].get(edge[1],0)+1\n",
    "                dic[edge[0]]['len']+=1\n",
    "            if dic.get(edge[1],None)==None:\n",
    "                dic[edge[1]]={edge[0]:1,'len':1}\n",
    "            else:\n",
    "                dic[edge[1]][edge[0]]=dic[edge[1]].get(edge[0],0)+1\n",
    "                dic[edge[1]]['len']+=1\n",
    "        for i in range(1,n+1):\n",
    "            if i in dic:\n",
    "                dicsort.append([i,dic[i]['len']])\n",
    "            else:\n",
    "                dicsort.append([i,0])\n",
    "        dicsort.sort(key=lambda x:x[1])\n",
    "        print(dicsort)\n",
    "        for k,target in enumerate(queries):\n",
    "            count=0\n",
    "            for i in dicsort:\n",
    "                derta=target-i[1]\n",
    "                left,right=0,len(dicsort)-1\n",
    "                if dicsort[right][1]<=derta:\n",
    "                    continue\n",
    "                elif dicsort[left][1]>derta:\n",
    "                    count+=n\n",
    "                else:\n",
    "                    while right-left>1:\n",
    "                        mid=(left+right)//2\n",
    "                        if dicsort[mid][1]<=derta:\n",
    "                            left=mid\n",
    "                        elif dicsort[mid][1]>derta:\n",
    "                            right=mid\n",
    "                        else:\n",
    "                            while dicsort[mid][1]==derta:\n",
    "                                mid+=1\n",
    "                            right=mid\n",
    "                            break\n",
    "                    count+=n-right\n",
    "                for edge in dic.get(i[0],[]):\n",
    "                    if edge!='len' and i[1]-dic[i[0]][edge]+dic[edge]['len']<=target and i[1]+dic[edge]['len']>target:\n",
    "                        count-=1\n",
    "                if i[1]+i[1]>target:\n",
    "                    count-=1\n",
    "            queries[k]=count//2 \n",
    "        return queries\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution(object):\n",
    "    def countPairs(self, n, edges, queries):\n",
    "        \"\"\"\n",
    "        :type n: int\n",
    "        :type edges: List[List[int]]\n",
    "        :type queries: List[int]\n",
    "        :rtype: List[int]\n",
    "        \"\"\"\n",
    "        dicsort=list()\n",
    "        dic=dict()\n",
    "        for edge in edges:\n",
    "            if dic.get(edge[0],None)==None:\n",
    "                dic[edge[0]]={edge[1]:1,'len':1}\n",
    "            else:\n",
    "                dic[edge[0]][edge[1]]=dic[edge[0]].get(edge[1],0)+1\n",
    "                dic[edge[0]]['len']+=1\n",
    "            if dic.get(edge[1],None)==None:\n",
    "                dic[edge[1]]={edge[0]:1,'len':1}\n",
    "            else:\n",
    "                dic[edge[1]][edge[0]]=dic[edge[1]].get(edge[0],0)+1\n",
    "                dic[edge[1]]['len']+=1\n",
    "        for i in range(1,n+1):\n",
    "            if i in dic:\n",
    "                dicsort.append([i,dic[i]['len']])\n",
    "            else:\n",
    "                dicsort.append([i,0])\n",
    "        dicsort.sort(key=lambda x:x[1])\n",
    "        print(dicsort)\n",
    "        for k,target in enumerate(queries):\n",
    "            count=0\n",
    "            for i in dicsort:\n",
    "                derta=target-i[1]\n",
    "                left,right=0,len(dicsort)-1\n",
    "                if dicsort[right][1]<=derta:\n",
    "                    continue\n",
    "                elif dicsort[left][1]>derta:\n",
    "                    count+=n\n",
    "                else:\n",
    "                    while right-left>1:\n",
    "                        mid=(left+right)//2\n",
    "                        if dicsort[mid][1]<=derta:\n",
    "                            left=mid\n",
    "                        elif dicsort[mid][1]>derta:\n",
    "                            right=mid\n",
    "                        else:\n",
    "                            while dicsort[mid][1]==derta:\n",
    "                                mid+=1\n",
    "                            right=mid\n",
    "                            break\n",
    "                    count+=n-right\n",
    "                for edge in dic.get(i[0],[]):\n",
    "                    if edge!='len' and i[1]-dic[i[0]][edge]+dic[edge]['len']<=target and i[1]+dic[edge]['len']>target:\n",
    "                        count-=1\n",
    "                if i[1]+i[1]>target:\n",
    "                    count-=1\n",
    "            queries[k]=count//2 \n",
    "        return queries\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, n: int, edges: List[List[int]], queries: List[int]) -> List[int]:\n",
    "        cnt=defaultdict(int)\n",
    "        node_sum=[0]*n\n",
    "        for a,b in edges:\n",
    "            a-=1\n",
    "            b-=1\n",
    "            node_sum[a]+=1\n",
    "            node_sum[b]+=1\n",
    "            cnt[(min(a,b),max(a,b))]+=1\n",
    "        node_sum_nums=sorted(node_sum)\n",
    "        res=[]\n",
    "        for quer in queries:\n",
    "            L,R=0,len(node_sum)-1\n",
    "            total=0\n",
    "            while L<R:\n",
    "                tmp_value=node_sum_nums[L]+node_sum_nums[R]\n",
    "                if tmp_value>quer:\n",
    "                    total+=R-L\n",
    "                    R-=1\n",
    "                else:\n",
    "                    L+=1\n",
    "            # 去掉不满足条件的\n",
    "            for (a,b),v in cnt.items():\n",
    "                if node_sum[a]+node_sum[b]>quer and  node_sum[a]+node_sum[b]-v<=quer:\n",
    "                    total-=1\n",
    "            res.append(total)\n",
    "        return res"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, n: int, edges: List[List[int]], queries: List[int]) -> List[int]:\n",
    "        def bisearch(val,a,l,r):\n",
    "            mid = r+1\n",
    "            if l>r:\n",
    "                return mid\n",
    "            while l<=r:\n",
    "                mid = (l + r)//2\n",
    "                if a[mid]<=val:\n",
    "                    l = mid+1\n",
    "                else:\n",
    "                    r = mid-1\n",
    "            return mid+1 if a[mid]<=val else mid\n",
    "        ans = [0]*len(queries)\n",
    "        nodes = [0] * n \n",
    "        graph = defaultdict(int)\n",
    "        for a,b in edges:\n",
    "            a -= 1\n",
    "            b -= 1\n",
    "            if a>b:\n",
    "                a,b = b,a\n",
    "            nodes[a]+=1\n",
    "            nodes[b]+=1\n",
    "            graph[(a,b)] +=1\n",
    "        lst = sorted(nodes)\n",
    "        for i in range(len(queries)):\n",
    "            for j in range(len(lst)):\n",
    "                r = queries[i]-lst[j]\n",
    "                index = bisearch(r,lst,j+1,len(lst)-1)\n",
    "                print(index)\n",
    "                ans[i]+=n-index\n",
    "            for key in graph:\n",
    "                a,b = key\n",
    "                if nodes[a]+nodes[b]>queries[i] and nodes[a]+nodes[b]-graph[key]<=queries[i]:\n",
    "                    ans[i]-=1\n",
    "        return ans"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, n: int, edges: List[List[int]], queries: List[int]) -> List[int]:\n",
    "        deg = [0] * n\n",
    "        overlap = dict()\n",
    "        connectedEdges = collections.defaultdict(int)\n",
    "\n",
    "        def getId(edge):\n",
    "            return min(edge) * (2* 10**5+1) + max(edge)\n",
    "        \n",
    "        for i, e in enumerate(edges):\n",
    "            u, v = e[0], e[1]\n",
    "            deg[u-1] += 1\n",
    "            deg[v-1] += 1\n",
    "\n",
    "            if getId(e) not in overlap:\n",
    "                overlap[getId(e)] = i\n",
    "            \n",
    "            connectedEdges[getId(e)] += 1\n",
    "        \n",
    "        ndeg = sorted(deg)\n",
    "        ret = []\n",
    "        for q in queries:\n",
    "            l, r = 0, n-1\n",
    "            cnt = 0\n",
    "            while l < n:\n",
    "                while r > l and ndeg[l] + ndeg[r] > q:\n",
    "                    r -= 1\n",
    "                cnt += n - max(l, r) - 1\n",
    "                l += 1\n",
    "            for i in overlap.values():\n",
    "                u, v = edges[i][0], edges[i][1]\n",
    "                if deg[u-1] + deg[v-1] > q and deg[u-1] + deg[v-1] - connectedEdges[getId(edges[i])] <= q:\n",
    "\n",
    "                    cnt -= 1\n",
    "            ret.append(cnt)\n",
    "        \n",
    "        return ret\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, n: int, edges: List[List[int]], queries: List[int]) -> List[int]:\n",
    "        graph = collections.Counter()\n",
    "        ind = [0] * n \n",
    "        for a, b in edges:\n",
    "            if a > b:\n",
    "                a, b = b, a\n",
    "            graph[(a - 1, b - 1)] += 1\n",
    "            ind[a - 1] += 1 \n",
    "            ind[b - 1] += 1 \n",
    "        sorted_ind = sorted(ind)\n",
    "        def binary_search(start, target):\n",
    "            if sorted_ind[-1] <= target:\n",
    "                return n\n",
    "            l = start\n",
    "            r = n - 1 \n",
    "            while l < r:\n",
    "                mid = l + (r - l) // 2 \n",
    "                if sorted_ind[mid] <= target:\n",
    "                    l = mid + 1 \n",
    "                else:\n",
    "                    r = mid \n",
    "            return l \n",
    "        res = []\n",
    "        for q in queries:\n",
    "            ans = 0\n",
    "            for i in range(n - 1):\n",
    "                idx = binary_search(i + 1, q - sorted_ind[i])\n",
    "                ans += n - idx \n",
    "            for a, b in graph:\n",
    "                if ind[a] + ind[b] > q and ind[a] + ind[b] - graph[(a, b)] <= q:\n",
    "                    ans -= 1 \n",
    "            res.append(ans)\n",
    "        return res \n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, n: int, edges: List[List[int]], queries: List[int]) -> List[int]:\n",
    "        graph = collections.Counter()\n",
    "        ind = [0] * n \n",
    "        for a, b in edges:\n",
    "            if a > b:\n",
    "                a, b = b, a\n",
    "            graph[(a - 1, b - 1)] += 1\n",
    "            ind[a - 1] += 1 \n",
    "            ind[b - 1] += 1 \n",
    "        sorted_ind = sorted(ind)\n",
    "        def binary_search(start, target):\n",
    "            if sorted_ind[-1] <= target:\n",
    "                return n\n",
    "            l = start\n",
    "            r = n - 1 \n",
    "            while l < r:\n",
    "                mid = l + (r - l) // 2 \n",
    "                if sorted_ind[mid] <= target:\n",
    "                    l = mid + 1 \n",
    "                else:\n",
    "                    r = mid \n",
    "            return l \n",
    "        res = []\n",
    "        for q in queries:\n",
    "            ans = 0\n",
    "            for i in range(n - 1):\n",
    "                idx = binary_search(i + 1, q - sorted_ind[i])\n",
    "                ans += n - idx \n",
    "            for a, b in graph:\n",
    "                if ind[a] + ind[b] > q and ind[a] + ind[b] - graph[(a, b)] <= q:\n",
    "                    ans -= 1 \n",
    "            res.append(ans)\n",
    "        return res \n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, n: int, edges: List[List[int]], queries: List[int]) -> List[int]:\n",
    "        res = [0] * len(queries)\n",
    "        cnt = [0] * n\n",
    "        e = dict()\n",
    "        for y in edges:\n",
    "            cnt[y[0]-1] += 1\n",
    "            cnt[y[1]-1] += 1\n",
    "            mi, ma = min(y[0], y[1]) - 1, max(y[0], y[1]) - 1\n",
    "            e.setdefault((mi, ma), 0)\n",
    "            e[(mi, ma)] += 1\n",
    "        z = sorted(cnt)\n",
    "        nn = len(z)\n",
    "        dd = dict()\n",
    "        cc = Counter(cnt)\n",
    "        @lru_cache(n)\n",
    "        def findy(jj, i):\n",
    "            if jj > queries[i]:\n",
    "                return n - 1\n",
    "            yy = bisect_right(z, queries[i] - jj)\n",
    "            return nn - yy - (2 * jj > queries[i])\n",
    "        for i in range(len(queries)):\n",
    "            if i in dd:\n",
    "                res[i] = dd[i]\n",
    "                continue\n",
    "            for j, ccc in cc.items():\n",
    "                res[i] += findy(j, i) * ccc\n",
    "            for edg, v in e.items():\n",
    "                if queries[i] < cnt[edg[0]] + cnt[edg[1]] <= v + queries[i]:\n",
    "                    res[i] -= 2\n",
    "            res[i] = res[i]// 2\n",
    "            dd[i] = res[i]\n",
    "        \n",
    "        return res\n",
    "\n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, n: int, edges: List[List[int]], queries: List[int]) -> List[int]:\n",
    "        degree = [0 for i in range(n)]\n",
    "        cnt = collections.defaultdict(int)\n",
    "        for edge in edges:\n",
    "            if edge[0] > edge[1]:\n",
    "                edge[1], edge[0] = edge[0], edge[1]\n",
    "            degree[edge[0] - 1] += 1\n",
    "            degree[edge[1] - 1] += 1\n",
    "            cnt[(edge[0] - 1, edge[1] - 1)] += 1\n",
    "        \n",
    "        arr = sorted(degree)\n",
    "        res = []\n",
    "        for q in queries:\n",
    "            ans = 0\n",
    "            i, j = 0, n - 1\n",
    "            while i < n:\n",
    "                while arr[i] + arr[j] > q and j > i:\n",
    "                    j -= 1\n",
    "                ans += n - 1 - max(i, j)\n",
    "                i += 1\n",
    "            for (x, y), freq in cnt.items():\n",
    "                if degree[x] + degree[y] > q and degree[x] + degree[y] - freq <= q:\n",
    "                    ans -= 1\n",
    "            res.append(ans)\n",
    "\n",
    "        return res\n",
    "    "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, n: int, edges: List[List[int]], queries: List[int]) -> List[int]:\n",
    "        d = defaultdict(set)\n",
    "        res = [0] * len(queries)\n",
    "        cnt = [0] * n\n",
    "        e = dict()\n",
    "        for y in edges:\n",
    "            cnt[y[0]-1] += 1\n",
    "            cnt[y[1]-1] += 1\n",
    "            e.setdefault(y[0]-1, dict())\n",
    "            e.setdefault(y[1]-1, dict())\n",
    "            e[y[0]-1].setdefault(y[1]-1, 0)\n",
    "            e[y[1]-1].setdefault(y[0]-1, 0)\n",
    "            e[y[0]-1][y[1]-1] += 1\n",
    "            e[y[1]-1][y[0]-1] += 1\n",
    "        from sortedcontainers import SortedList\n",
    "        yy = SortedList(cnt)\n",
    "        for i in range(len(queries)):\n",
    "            z = yy.copy()\n",
    "            for x, j in enumerate(cnt):\n",
    "                if j > queries[i]:\n",
    "                    res[i] += n - 1 - x\n",
    "                    z.pop(z.index(j))\n",
    "                    continue\n",
    "                z.pop(z.index(j))\n",
    "                y = z.bisect_right(queries[i] - j)\n",
    "                res[i] += len(z) - y\n",
    "                if x in e:\n",
    "                    for edg in e[x]:\n",
    "                        if edg > x and cnt[edg] + j - e[x][edg] <= queries[i] and cnt[edg] + j > queries[i]:\n",
    "                            res[i] -= 1\n",
    "        \n",
    "        return res\n",
    "\n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, n: int, edges: List[List[int]], queries: List[int]) -> List[int]:\n",
    "        g = [Counter() for _ in range(n)]\n",
    "        deg = [0] * n\n",
    "        for a, b in edges:\n",
    "            a -= 1\n",
    "            b -= 1\n",
    "            deg[a] += 1\n",
    "            deg[b] += 1\n",
    "            g[a][b] += 1\n",
    "            g[b][a] += 1\n",
    "        idx = list(range(n))\n",
    "        idx.sort(key=lambda i:deg[i])\n",
    "        pos = [0] * n\n",
    "        for i in range(n):\n",
    "            pos[idx[i]] = i\n",
    "         # print(idx, [deg[i] for i in idx])\n",
    "        ret = [0] * len(queries)\n",
    "        \n",
    "        for k, q in enumerate(queries):\n",
    "            l, r = 0, n - 1\n",
    "            while l < r:\n",
    "                if deg[idx[l]] + deg[idx[r]] > q:\n",
    "                    ret[k] += r - l\n",
    "                    need = q + 1 - deg[idx[r]]\n",
    "                    for son, cnt in g[idx[r]].items():\n",
    "                        if pos[son] < r and deg[son] - cnt < need and deg[son] >= need:\n",
    "                            ret[k] -= 1 \n",
    "                    r -= 1\n",
    "                else:\n",
    "                    l += 1     \n",
    "        return ret"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, n: int, edges: List[List[int]], queries: List[int]) -> List[int]:\n",
    "        g = [Counter() for _ in range(n)]\n",
    "        deg = [0] * n\n",
    "        for a, b in edges:\n",
    "            a -= 1\n",
    "            b -= 1\n",
    "            deg[a] += 1\n",
    "            deg[b] += 1\n",
    "            g[a][b] += 1\n",
    "            g[b][a] += 1\n",
    "        idx = list(range(n))\n",
    "        idx.sort(key=lambda i:deg[i])\n",
    "        pos = [0] * n\n",
    "        for i in range(n):\n",
    "            pos[idx[i]] = i\n",
    "         # print(idx, [deg[i] for i in idx])\n",
    "        ret = [0] * len(queries)\n",
    "        for k, q in enumerate(queries):\n",
    "            for i in range(1, n):\n",
    "                need = q + 1 - deg[idx[i]]\n",
    "                need = q - deg[idx[i]] + 1\n",
    "                l, r = 0, i - 1\n",
    "                while l <= r:\n",
    "                    m = l + r >> 1\n",
    "                    if deg[idx[m]] >= need:\n",
    "                        r = m - 1\n",
    "                    else:\n",
    "                        l = m + 1\n",
    "                if i == l:\n",
    "                    continue\n",
    "                ret[k] += i - l\n",
    "\n",
    "                for son, cnt in g[idx[i]].items():\n",
    "                    if pos[son] < i and deg[son] - cnt < need and deg[son] >= need:\n",
    "                        ret[k] -= 1              \n",
    "        return ret"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, n: int, edges: List[List[int]], queries: List[int]) -> List[int]:\n",
    "        deg = [0] * (n)\n",
    "        g = []\n",
    "        for a, b in edges:\n",
    "            a, b = a - 1, b - 1\n",
    "            a, b = min(a, b), max(a, b)\n",
    "            deg[a] += 1\n",
    "            deg[b] += 1\n",
    "            g.append((a, b))\n",
    "        sorted_deg = sorted(deg)\n",
    "        cnt = Counter(g)\n",
    "        print(sorted_deg)\n",
    "        ans = [0] * len(queries)\n",
    "        for i, q in enumerate(queries):\n",
    "            for j, x in enumerate(sorted_deg):\n",
    "                k = bisect_right(sorted_deg, q - x, lo = j + 1)\n",
    "                ans[i] += n - k\n",
    "            for (a, b), t in cnt.items():\n",
    "                if q < deg[a] + deg[b] <= q + t:\n",
    "                    ans[i] -= 1\n",
    "        return ans\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, n: int, edges: List[List[int]], queries: List[int]) -> List[int]:\n",
    "        a = [0] * (n+1)\n",
    "        d = defaultdict(int)\n",
    "\n",
    "        for e in edges:\n",
    "            a[e[0]] += 1\n",
    "            a[e[1]] += 1\n",
    "        \n",
    "        for i in range(1, n+1):\n",
    "            d[a[i]] += 1\n",
    "        \n",
    "        ans = defaultdict(int)\n",
    "        ds = list(d.keys())\n",
    "        for i in range(len(ds)):\n",
    "            for j in range(i+1):\n",
    "                if i==j:\n",
    "                    ans[ds[i]<<1] += d[ds[i]] * (d[ds[i]]-1) >> 1\n",
    "                else:\n",
    "                    ans[ds[i]+ds[j]] += d[ds[i]] * d[ds[j]]\n",
    "\n",
    "        edges = [tuple(sorted(i)) for i in edges]\n",
    "        cnt = defaultdict(lambda: defaultdict(int))\n",
    "        for e in edges:\n",
    "            cnt[e[0]][e[1]] += 1\n",
    "        \n",
    "        for e in edges:\n",
    "            x, y = e\n",
    "            if cnt[x][y]:\n",
    "                ans[a[x]+a[y]] -= 1\n",
    "                ans[a[x]+a[y]-cnt[x][y]] += 1\n",
    "                cnt[x][y] = 0\n",
    "        \n",
    "        for i in range(max(queries)+2):\n",
    "            ans[i] += ans[i-1]\n",
    "        \n",
    "        al = n * (n-1) >> 1\n",
    "        res = [al - ans[i] for i in queries]\n",
    "        return res"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "from collections import defaultdict, Counter\n",
    "class Solution:\n",
    "    def countPairs(self, n: int, edges: List[List[int]], queries: List[int]) -> List[int]:\n",
    "        def count(nums):\n",
    "            sums = 0\n",
    "            for e in nums:\n",
    "                sums += e\n",
    "            return sums\n",
    "\n",
    "        edge = [defaultdict(int) for _ in range(n+1)]\n",
    "        edge_cnt = Counter()\n",
    "        # edges = list(set(edges))\n",
    "        for e in edges:\n",
    "            a, b = e[0], e[1]\n",
    "            if a>b:\n",
    "                a, b = b, a\n",
    "            \n",
    "            edge[a][b] += 1\n",
    "            edge[b][a] += 1\n",
    "            edge_cnt[(a, b)] += 1\n",
    "        # for i in range(n+1):\n",
    "            # v = edges[i].values()\n",
    "\n",
    "            \n",
    "\n",
    "\n",
    "        ori_n2c = [count(edge[i].values()) for i in range(n+1)]\n",
    "        # print(n2c)\n",
    "        # print(edge_cnt)\n",
    "        n2c = sorted(ori_n2c)\n",
    "        l = len(queries)\n",
    "        ans = [0] * l\n",
    "        # print(n2c)\n",
    "        for k in range(l):\n",
    "            for i in range(1, n+1):\n",
    "                h = i+1\n",
    "                t = n\n",
    "                pos = -1\n",
    "                while t >= h:\n",
    "                    m = (h+t) // 2\n",
    "                    # print(m)\n",
    "                    if n2c[m] > queries[k] - n2c[i]:\n",
    "                        pos = m\n",
    "                        t = m - 1\n",
    "                    else: \n",
    "                        h = m + 1\n",
    "                    # else:\n",
    "                        # t = m\n",
    "                        # break\n",
    "                t += 1\n",
    "                # if n2c[h] == queries[k] - n2c[i]:\n",
    "                if t < n + 1:\n",
    "                # if pos != -1:\n",
    "                    ans[k] += n - t + 1\n",
    "            # print(ans)\n",
    "            for (a,b), cnt in edge_cnt.items():\n",
    "                if ori_n2c[a] + ori_n2c[b] > queries[k] and ori_n2c[a] + ori_n2c[b] - cnt <= queries[k]:\n",
    "                    # print(a,b,cnt)\n",
    "                    ans[k] -= 1\n",
    "        return ans "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, n: int, edges: List[List[int]], queries: List[int]) -> List[int]:\n",
    "        deg = [0] * n\n",
    "        cnt = {}\n",
    "        for x, y in edges:\n",
    "            x -= 1\n",
    "            y -= 1\n",
    "            if x > y: x, y = y, x\n",
    "            deg[x] += 1\n",
    "            deg[y] += 1\n",
    "            cnt[x, y] = cnt.get((x, y), 0) + 1\n",
    "        a = sorted(deg[x] + deg[y] for x, y in cnt)\n",
    "        b = sorted(deg[x] + deg[y] - cnt[x, y] for x, y in cnt)\n",
    "        deg.sort()\n",
    "        deg2 = [x + y for x, y in pairwise(deg)]\n",
    "        res = []\n",
    "        for q in queries:\n",
    "            if q >= deg2[-1]:\n",
    "                res.append(0)\n",
    "                continue\n",
    "            left = bisect_right(deg, q - deg[-1])\n",
    "            right = bisect_right(deg2, q)\n",
    "            t = comb(n, 2) + comb(right + 1, 2) - n * left\n",
    "            res.append(\n",
    "                t - sum(bisect_right(deg, q - deg[i], i + 1) for i in range(left, right))\n",
    "                + bisect_right(a, q) - bisect_right(b, q)\n",
    "            )\n",
    "        return res"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, n: int, edges: List[List[int]], queries: List[int]) -> List[int]:\n",
    "        deg = [0] * n\n",
    "        cnt = Counter()\n",
    "        for x, y in edges:\n",
    "            x -= 1\n",
    "            y -= 1\n",
    "            deg[x] += 1\n",
    "            deg[y] += 1\n",
    "            if x > y: x, y = y, x\n",
    "            cnt[x, y] += 1\n",
    "        a, b = [], []\n",
    "        for x, y in cnt:\n",
    "            t = deg[x] + deg[y]\n",
    "            a.append(t)\n",
    "            b.append(t - cnt[x, y])\n",
    "        a.sort()\n",
    "        b.sort()\n",
    "        deg.sort()\n",
    "        n2 = comb(n, 2)\n",
    "        q0 = n2 - comb(bisect_right(deg, 0), 2)\n",
    "        deg2 = [x + y for x, y in pairwise(deg)]\n",
    "        res = []\n",
    "        for q in queries:\n",
    "            if q >= deg2[-1]:\n",
    "                res.append(0)\n",
    "                continue\n",
    "            if q == 0:\n",
    "                res.append(q0)\n",
    "                continue\n",
    "            left = bisect_right(deg, q - deg[-1])\n",
    "            right = bisect_right(deg2, q)\n",
    "            res.append(\n",
    "                n2 + comb(right + 1, 2) - n * left\n",
    "                - sum(bisect_right(deg, q - deg[i], i + 1) for i in range(left, right))\n",
    "                + bisect_right(a, q) - bisect_right(b, q)\n",
    "            )\n",
    "        return res"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, n: int, edges: List[List[int]], queries: List[int]) -> List[int]:\n",
    "        deg = [0] * n\n",
    "        cnt = {}\n",
    "        for x, y in edges:\n",
    "            x -= 1\n",
    "            y -= 1\n",
    "            deg[x] += 1\n",
    "            deg[y] += 1\n",
    "            if x > y: x, y = y, x\n",
    "            cnt[x, y] = cnt.get((x, y), 0) + 1\n",
    "        a = sorted(deg[x] + deg[y] for x, y in cnt)\n",
    "        b = sorted(deg[x] + deg[y] - cnt[x, y] for x, y in cnt)\n",
    "        deg.sort()\n",
    "        n2 = comb(n, 2)\n",
    "        q0 = n2 - comb(bisect_right(deg, 0), 2)\n",
    "        deg2 = [x + y for x, y in pairwise(deg)]\n",
    "        res = []\n",
    "        for q in queries:\n",
    "            if q >= deg2[-1]:\n",
    "                res.append(0)\n",
    "                continue\n",
    "            if q == 0:\n",
    "                res.append(q0)\n",
    "                continue\n",
    "            left = bisect_right(deg, q - deg[-1])\n",
    "            right = bisect_right(deg2, q)\n",
    "            res.append(\n",
    "                n2 + comb(right + 1, 2) - n * left\n",
    "                - sum(bisect_right(deg, q - deg[i], i + 1) for i in range(left, right))\n",
    "                + bisect_right(a, q) - bisect_right(b, q)\n",
    "            )\n",
    "        return res"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, n: int, edges: List[List[int]], queries: List[int]) -> List[int]:\n",
    "        deg = [0] * n\n",
    "        cnt = {}\n",
    "        for x, y in edges:\n",
    "            x -= 1\n",
    "            y -= 1\n",
    "            deg[x] += 1\n",
    "            deg[y] += 1\n",
    "            if x > y: x, y = y, x\n",
    "            cnt[x, y] = cnt.get((x, y), 0) + 1\n",
    "        a = sorted(deg[x] + deg[y] for x, y in cnt)\n",
    "        b = sorted(deg[x] + deg[y] - cnt[x, y] for x, y in cnt)\n",
    "        deg.sort()\n",
    "        n2 = comb(n, 2)\n",
    "        q0 = n2 - comb(bisect_right(deg, 0), 2)\n",
    "        deg2 = [x + y for x, y in pairwise(deg)]\n",
    "        res = []\n",
    "        for q in queries:\n",
    "            if q >= deg2[-1]:\n",
    "                res.append(0)\n",
    "                continue\n",
    "            if q == 0:\n",
    "                res.append(q0)\n",
    "                continue\n",
    "            left = bisect_right(deg, q - deg[-1])\n",
    "            right = bisect_right(deg2, q)\n",
    "            res.append(\n",
    "                n2 + comb(right + 1, 2) - n * left\n",
    "                - sum(bisect_right(deg, q - deg[i], i + 1) for i in range(left, right))\n",
    "                + bisect_right(a, q) - bisect_right(b, q)\n",
    "            )\n",
    "        return res"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# class Solution:\n",
    "#     def countPairs(self, n: int, edges: List[List[int]], queries: List[int]) -> List[int]:\n",
    "#         degree = [0 for _ in range(n)]\n",
    "#         cnt = collections.defaultdict(int)\n",
    "#         for edge in edges:\n",
    "#             x, y = edge[0] - 1, edge[1] - 1\n",
    "#             if x > y:\n",
    "#                 x, y = y, x\n",
    "#             degree[x] += 1\n",
    "#             degree[y] += 1\n",
    "#             cnt[x * n + y] += 1\n",
    "\n",
    "#         arr = sorted(degree)\n",
    "#         ans = []\n",
    "#         for bound in queries:\n",
    "#             total = 0\n",
    "#             for i in range(n):\n",
    "#                 j = bisect_right(arr, bound - arr[i], i + 1)\n",
    "#                 total += n - j\n",
    "#             for val, freq in cnt.items():\n",
    "#                 x, y = val // n, val % n\n",
    "#                 if degree[x] + degree[y] > bound and degree[x] + degree[y] - freq <= bound:\n",
    "#                     total -= 1\n",
    "#             ans.append(total)\n",
    "#         return ans\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(\n",
    "        self, n: int, edges: List[List[int]], queries: List[int]\n",
    "    ) -> List[int]:\n",
    "        cnt = [0] * n\n",
    "        g = defaultdict(int)\n",
    "        for a, b in edges:\n",
    "            a, b = a - 1, b - 1\n",
    "            a, b = min(a, b), max(a, b)\n",
    "            cnt[a] += 1\n",
    "            cnt[b] += 1\n",
    "            g[(a, b)] += 1\n",
    "\n",
    "        s = sorted(cnt)\n",
    "        ans = [0] * len(queries)\n",
    "        for i, t in enumerate(queries):\n",
    "            for j, x in enumerate(s):\n",
    "                k = bisect_right(s, t - x, lo=j + 1)\n",
    "                ans[i] += n - k\n",
    "            for (a, b), v in g.items():\n",
    "                if cnt[a] + cnt[b] > t and cnt[a] + cnt[b] - v <= t:\n",
    "                    ans[i] -= 1\n",
    "        return ans\n",
    "\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, n: int, edges: List[List[int]], queries: List[int]) -> List[int]:\n",
    "        # 1. build degree list of undirected graph\n",
    "        edgeCounter = Counter(tuple(sorted([u-1, v-1])) for u, v in edges)\n",
    "        degree = [0] * n \n",
    "        for u, v in edgeCounter:\n",
    "            degree[u] += edgeCounter[(u, v)]\n",
    "            degree[v] += edgeCounter[(u, v)]\n",
    "        \n",
    "        # 2. binary search\n",
    "        sorted_deg = sorted(degree)\n",
    "        ans = [0] * len(queries)\n",
    "        for i, q in enumerate(queries):\n",
    "            l, r = 0, n-1\n",
    "            while l < r:\n",
    "                if sorted_deg[l] + sorted_deg[r] <= q:\n",
    "                    l += 1\n",
    "                else:\n",
    "                    ans[i] += r-l \n",
    "                    r -= 1 \n",
    "            for (u, v), count in edgeCounter.items():\n",
    "                if q < degree[u] + degree[v] <= q + count:\n",
    "                    ans[i] -= 1\n",
    "        return ans \n",
    "\n",
    "\n",
    "\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, n: int, edges: List[List[int]], queries: List[int]) -> List[int]:\n",
    "        degree = [0]*n\n",
    "        freq = defaultdict(int)\n",
    "        for u, v in edges: \n",
    "            degree[u-1] += 1\n",
    "            degree[v-1] += 1\n",
    "            freq[min(u-1, v-1), max(u-1, v-1)] += 1\n",
    "        \n",
    "        vals = sorted(degree)\n",
    "        \n",
    "        ans = []\n",
    "        for query in queries: \n",
    "            cnt = 0 \n",
    "            lo, hi = 0, n-1\n",
    "            while lo < hi: \n",
    "                if query < vals[lo] + vals[hi]: \n",
    "                    cnt += hi - lo # (lo, hi), (lo+1, hi), ..., (hi-1, hi) all valid\n",
    "                    hi -= 1\n",
    "                else: lo += 1\n",
    "            for u, v in freq: \n",
    "                if degree[u] + degree[v] - freq[u, v] <= query < degree[u] + degree[v]: cnt -= 1\n",
    "            ans.append(cnt)\n",
    "        return ans"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, n: int, edges: List[List[int]], queries: List[int]) -> List[int]:\n",
    "        cnt = [0] * n\n",
    "        g = defaultdict(int)\n",
    "        for a, b in edges:\n",
    "            a, b = a - 1, b - 1\n",
    "            a, b = min(a, b), max (a, b)\n",
    "            cnt[a] += 1\n",
    "            cnt[b] += 1\n",
    "            g[(a, b)] += 1\n",
    "        s = sorted(cnt)\n",
    "        ans = [0] * len(queries)\n",
    "        for i, t in enumerate(queries):\n",
    "            for j, x in enumerate(s):\n",
    "                k = bisect_right(s, t - x, lo = j + 1)\n",
    "                ans[i] += n - k\n",
    "            for (a, b), v in g.items():\n",
    "                if cnt[a] + cnt[b] > t and cnt[a] + cnt[b] - v <= t:\n",
    "                    ans[i] -= 1\n",
    "        return ans "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# https://leetcode.cn/u/l00/\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, coordinates: List[List[int]], k: int) -> int:\n",
    "        # 减值思维\n",
    "        # ans, dic = 0, defaultdict(int)\n",
    "        # for x, y in coordinates: dic[(x,y)] += 1\n",
    "        # for x, y in coordinates:\n",
    "        #     dic[(x,y)] -= 1\n",
    "        #     for i in range(k + 1):\n",
    "        #         p = (i ^ x, (k - i) ^ y)\n",
    "        #         if p in dic: ans += dic[p]\n",
    "        # return ans\n",
    "\n",
    "        # 增值思维\n",
    "        ans, dic = 0, defaultdict(int)\n",
    "        for x, y in coordinates:\n",
    "            for i in range(k + 1):\n",
    "                p = (i ^ x, (k - i) ^ y)\n",
    "                if p in dic: ans += dic[p]\n",
    "            dic[(x,y)] += 1\n",
    "        return ans"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, coordinates: List[List[int]], k: int) -> int:\n",
    "        ans = 0\n",
    "        cnt = Counter()\n",
    "        for x, y in coordinates:\n",
    "            for i in range(k + 1):\n",
    "                ans += cnt[x ^ i, y ^ (k - i)]  # tuple 的括号可以省略\n",
    "            cnt[x, y] += 1  # tuple 的括号可以省略\n",
    "        return ans"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, coordinates: List[List[int]], k: int) -> int:\n",
    "        ans = 0\n",
    "        cnt = Counter()\n",
    "        for x, y in coordinates:\n",
    "            for i in range(k + 1):\n",
    "                ans += cnt[x ^ i, y ^ (k - i)]  # tuple 的括号可以省略\n",
    "            cnt[x, y] += 1  # tuple 的括号可以省略\n",
    "        return ans"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, coordinates: List[List[int]], k: int) -> int:\n",
    "        ans = 0\n",
    "        d = dict()\n",
    "        for v in coordinates:\n",
    "            for i in range(k+1):\n",
    "                x = i^v[0]\n",
    "                y = (k-i)^v[1]\n",
    "                ans += d.get((x,y),0)\n",
    "            if (v[0],v[1]) not in d:\n",
    "                d[(v[0],v[1])] = 0\n",
    "            d[(v[0],v[1])] += 1\n",
    "        return ans"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, coordinates: List[List[int]], k: int) -> int:\n",
    "        ans = 0\n",
    "        d = Counter()\n",
    "        for v in coordinates:\n",
    "            for i in range(k+1):\n",
    "                ans += d[i^v[0],(k-i)^v[1]]\n",
    "            d[v[0],v[1]] += 1\n",
    "        return ans"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, coordinates: List[List[int]], k: int) -> int:\n",
    "        # (x1 xor x2) + (y1 xor y2) == k\n",
    "        # 0 <= x1 xor x2 <= k  and 0 <= y1 xor y2 <= k\n",
    "        # 如果 x1 xor x2 = i   y1 xor y2 = k - i\n",
    "        # -> x1 = x2 xor i   y1 = y2 xor i\n",
    "        # 枚举 x2 和 y2 以及\n",
    "        # cnt 记录出现过的坐标\n",
    "        cnt = Counter()\n",
    "        ans = 0\n",
    "        for x, y in coordinates:\n",
    "            for i in range(k + 1):\n",
    "                ans += cnt[(x ^ i, y ^(k - i))]\n",
    "            cnt[(x, y)] += 1\n",
    "        return ans"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, coordinates: List[List[int]], k: int) -> int:\n",
    "        # 这是一个典型的需要考虑自己学会分析清楚复杂度的题目\n",
    "        # 朴素的思路里，需要两层for两两比对判断才能知道距离是不是k\n",
    "        # 但是这一题里，k的数值范围小\n",
    "        # 所以这里需要变成\n",
    "        # 点对(X,Y);(U,V);  K == K1 + K2\n",
    "        # 且满足 x^u == k1, y^v == k2\n",
    "        # 那么变成了找 u = k1 ^ x; v = k2 ^ y\n",
    "        # 枚举 k1,k2即可\n",
    "        ans = 0\n",
    "        rec = collections.defaultdict(int)\n",
    "        for x,y in coordinates:\n",
    "            rec[(x,y)] += 1\n",
    "\n",
    "        # 注意重复计数策略，当(X,Y) != (U,V)时候，只是val1 * val2 /2\n",
    "        # 当(X,Y) != (U,V)， 是val * (val - 1) / 2\n",
    "        # 对拍的时候的坑， 注意位运算一定要打括号！！！\n",
    "\n",
    "        for k1 in range(0, k+1):\n",
    "            k2 = k - k1 \n",
    "            for x,y in rec.keys():\n",
    "                u, v = (k1 ^ x, k2 ^ y)\n",
    "                val1 = rec.get((x,y), 0)\n",
    "                val2 = rec.get((u,v), 0)\n",
    "                if (x,y) == (u,v):\n",
    "                    ans += val1 * (val1 - 1) / 2\n",
    "                else: \n",
    "                    ans += val1 * val2 / 2\n",
    "        return int(ans) \n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, coordinates: List[List[int]], k: int) -> int:\n",
    "        dic = {}\n",
    "        \n",
    "        for x,y in coordinates:\n",
    "            if x in dic: dic[x][y] += 1\n",
    "            else: dic[x] = Counter([y])\n",
    "        \n",
    "        ans = 0\n",
    "        for x,y in coordinates:\n",
    "            dic[x][y] -= 1\n",
    "            for i in range(k+1):\n",
    "                m = x ^ i\n",
    "                if m in dic and  k - i >= 0:\n",
    "                    n = (k - i) ^ y\n",
    "                    # print((x,y),\"i\",i,\"m\",m,\"n\",n,\"cnt\",dic[m][n])\n",
    "                    # if m in dic:\n",
    "                    ans += dic[m][n]\n",
    "        return ans"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "from collections import *\n",
    "from sortedcontainers import *\n",
    "from heapq import *\n",
    "from sys import *\n",
    "from math import *\n",
    "from itertools import *\n",
    "from functools import *\n",
    "from string import *\n",
    "from bisect import *\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, coordinates: List[List[int]], k: int) -> int:\n",
    "        cnts = Counter()\n",
    "        ans = 0\n",
    "        for x, y in coordinates:\n",
    "            for i in range(k+1):\n",
    "                x1, y1 = x^i, (k - i) ^ y\n",
    "                ans += cnts[x1, y1]\n",
    "            cnts[x, y] += 1\n",
    "        return ans"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, coordinates: List[List[int]], k: int) -> int:\n",
    "        d = Counter([(x, y) for x, y in coordinates])\n",
    "        print(d)\n",
    "\n",
    "        ret = 0\n",
    "        for (x1, y1), cnt in d.items():\n",
    "            for i in range(k+1):\n",
    "                x2 = i ^ x1\n",
    "                y2 = (k-i) ^ y1\n",
    "                if (x2, y2) in d:\n",
    "                    if (x1, y1) == (x2, y2):\n",
    "                        # ret += int(math.perm(cnt, 2))\n",
    "                        ret += cnt * (cnt - 1)\n",
    "                    else:\n",
    "                        ret += cnt * d[(x2, y2)]\n",
    "\n",
    "        return ret // 2\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, a: List[List[int]], k: int) -> int:\n",
    "        n = len(bin(k)[2:])\n",
    "       \n",
    "        if k==0:\n",
    "            n = 0   \n",
    "        t = (1<<n)\n",
    "        ans = 0\n",
    "        def f(x):\n",
    "            if x>=t:\n",
    "                res = x>>n \n",
    "                res = res<<n\n",
    "                pre = bin(x>>n)[2:]\n",
    "                res = x - res \n",
    "                return [pre, res]\n",
    "                \n",
    "            else:\n",
    "                return ['s', x]\n",
    "            \n",
    "            \n",
    "        def p(x, y)  :\n",
    "            return (x[0]^y[0]) + (x[1]^y[1])\n",
    "        def g(x):\n",
    "            ans = 0\n",
    "            tmp = Counter()\n",
    "            for i, j in x:\n",
    "                tmp[(i, j)] += 1 \n",
    "            l = list(tmp.keys())\n",
    "            for i in range(len(l)):\n",
    "                for j in range(i+1, len(l)):\n",
    "                    if p(l[i], l[j])==k:\n",
    "                        ans += tmp[l[i]]*tmp[l[j]] \n",
    "            for j in tmp:\n",
    "                if p(j, j)==k:\n",
    "                    u = tmp[j]\n",
    "                    u = u*(u-1)//2\n",
    "                    ans += u \n",
    "            return ans \n",
    "            \n",
    "            \n",
    "        b = defaultdict(list)\n",
    "        for x, y in a:\n",
    "            c = f(x)\n",
    "            d = f(y)\n",
    "            b[(c[0], d[0])].append([c[1], d[1]]) \n",
    "        for j in b.values():\n",
    "            ans += g(j)\n",
    "        return ans \n",
    "            \n",
    "            \n",
    "            \n",
    "                "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "from typing import List\n",
    "\n",
    "\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, coordinates: List[List[int]], _k: int) -> int:\n",
    "        hmap = {}\n",
    "        res = 0\n",
    "        for pair in coordinates:\n",
    "            first = self.first_key(pair)\n",
    "            if first in hmap:\n",
    "                bucket = hmap[first]\n",
    "                for k in bucket:\n",
    "                    if (pair[0] ^ (first[0] + k[0])) + (pair[1] ^ (first[1] + k[1])) == _k:\n",
    "                        res += bucket[k]\n",
    "            self.insert(hmap, pair)\n",
    "        return res\n",
    "\n",
    "    def first_key(self, pair: List[int]):\n",
    "        return (pair[0] & ~127, pair[1] & ~127)\n",
    "    def secord_key(self, pair: List[int]):\n",
    "        return (pair[0] & 127, pair[1] & 127)\n",
    "\n",
    "    def insert(self, hmap, pair: List[int]):\n",
    "        first = self.first_key(pair)\n",
    "        second = self.secord_key(pair)\n",
    "        \n",
    "        if first not in hmap:\n",
    "            hmap[first] = {}\n",
    "        if second not in hmap[first]:\n",
    "            hmap[first][second] = 0\n",
    "        hmap[first][second] += 1\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# class Solution:\n",
    "#     def countPairs(self, coordinates: List[List[int]], k: int) -> int:\n",
    "#         ans = 0\n",
    "#         n = len(coordinates)\n",
    "#         cnt = Counter()\n",
    "\n",
    "#         for x,y in coordinates:\n",
    "#             for i in range(k+1):\n",
    "#                 ans += cnt[x^i, y^(k-i)]\n",
    "#             cnt[x,y] += 1\n",
    "\n",
    "#         return ans\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, coordinates: List[List[int]], k: int) -> int:\n",
    "        b7 = 0b11111_11\n",
    "        f13 = 0b11111_11111_11100_00000\n",
    "        di = collections.defaultdict(collections.Counter)        \n",
    "        ans = 0\n",
    "        for i, (x, y) in enumerate(coordinates):\n",
    "            fx, bx = x & f13, x & b7\n",
    "            fy, by = y & f13, y & b7\n",
    "            key, val = (fx, fy), (bx, by)\n",
    "            for (sx, sy), s in di[key].items():\n",
    "                if (bx ^ sx) + (by ^ sy) == k:\n",
    "                    ans += s\n",
    "            di[key][val] += 1\n",
    "        # print(di)\n",
    "        return ans"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, coordinates: List[List[int]], k: int) -> int:\n",
    "        # 二进制前10位的组合共有1024种\n",
    "        dict_ = defaultdict(list)\n",
    "        for x, y in coordinates:\n",
    "            pair = x >> 10, y >> 10\n",
    "            dict_[pair].append((x & 1023, y & 1023))\n",
    "        ans = 0\n",
    "        for pairs in dict_.values():\n",
    "            if len(pairs) < 2: continue\n",
    "            counter = Counter(pairs)\n",
    "            keys = list(counter.keys())\n",
    "            for i, (x1, y1) in enumerate(keys):\n",
    "                if (x1 ^ x1) + (y1 ^ y1) == k:\n",
    "                    ans += counter[(x1, y1)] * (counter[(x1, y1)] - 1) // 2\n",
    "                for x2, y2 in keys[i + 1:]:\n",
    "                    if (x1 ^ x2) + (y1 ^ y2) == k:\n",
    "                        ans += counter[(x1, y1)] * counter[(x2, y2)]\n",
    "        return ans"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, coordinates: List[List[int]], k: int) -> int:\n",
    "        b7 = 0b11111_11\n",
    "        f13 = 0b11111_11111_11100_00000\n",
    "        di = collections.defaultdict(collections.Counter)        \n",
    "        ans = 0\n",
    "        for i, (x, y) in enumerate(coordinates):\n",
    "            fx, bx = x & f13, x & b7\n",
    "            fy, by = y & f13, y & b7\n",
    "            key, val = (fx, fy), (bx, by)\n",
    "            for (sx, sy), s in di[key].items():\n",
    "                if (bx ^ sx) + (by ^ sy) == k:\n",
    "                    ans += s\n",
    "            di[key][val] += 1\n",
    "        # print(di)\n",
    "        return ans"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, coordinates: List[List[int]], k: int) -> int:\n",
    "        def check(x, y):\n",
    "            # print(x, y)\n",
    "            return ((x[0]^y[0]) + (x[1]^y[1])) == k\n",
    "        \n",
    "        digit = 0\n",
    "        kk = k\n",
    "        while kk:\n",
    "            kk >>= 1\n",
    "            digit += 1\n",
    "        mk = (1>>digit)-1\n",
    "        # print(\"digit\", digit, mk)\n",
    "        a = defaultdict(Counter)\n",
    "        for i, j in coordinates:\n",
    "            pos = (i>>digit) * 1000000 + (j>>digit)\n",
    "            a[pos][(i&mk, j&mk)] += 1\n",
    "        res = 0\n",
    "        # print(a)\n",
    "        for _, dic in a.items():\n",
    "            # print(dic)\n",
    "            lis = list(dic.keys())\n",
    "            for i in range(len(lis)):\n",
    "                if check(lis[i], lis[i]):\n",
    "                    res += (dic[lis[i]] * (dic[lis[i]]-1))//2\n",
    "                    # print(1, res)\n",
    "                for j in range(i+1, len(lis)):\n",
    "                    if check(lis[i], lis[j]):\n",
    "                        # print(dic, i, j)\n",
    "                        res += dic[lis[i]] * dic[lis[j]]\n",
    "                        # print(2, res)\n",
    "        return res\n",
    "                "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, coordinates: List[List[int]], k: int) -> int:\n",
    "        res = 0\n",
    "        dct_x = defaultdict(lambda: defaultdict(Counter))\n",
    "        for x,y in coordinates:\n",
    "            for x2,d2 in dct_x[x>>7].items():\n",
    "                if x^x2<=k:\n",
    "                    y2 = (k-(x^x2))^y\n",
    "                    res += d2[y2]\n",
    "            dct_x[x>>7][x][y]+=1\n",
    "        return res"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, coordinates: List[List[int]], k: int) -> int:\n",
    "        b10 = 0b11111_11111\n",
    "        f10 = 0b11111_11111_00000_00000\n",
    "        di = defaultdict(Counter)        \n",
    "        ans = 0\n",
    "        for i, (x, y) in enumerate(coordinates):\n",
    "            fx, bx = x & f10, x & b10\n",
    "            fy, by = y & f10, y & b10\n",
    "            key, val = (fx, fy), (bx, by)\n",
    "            for (sx, sy), s in di[key].items():\n",
    "                if (bx ^ sx) + (by ^ sy) == k:\n",
    "                    ans += s\n",
    "            di[key][val] += 1\n",
    "        # print(di)\n",
    "        return ans"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, coordinates: List[List[int]], k: int) -> int:\n",
    "        ans = 0\n",
    "        cnt = defaultdict(int)\n",
    "        for x, y in coordinates:\n",
    "            for i in range(k + 1):\n",
    "                ans += cnt[((x ^ i) << 20) + (y ^ (k - i))]\n",
    "            cnt[(x << 20) + y] += 1\n",
    "        return ans\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, coordinates: List[List[int]], k: int) -> int:\n",
    "        ans = 0\n",
    "        cnt = defaultdict(int)\n",
    "        for x, y in coordinates:\n",
    "            for i in range(k + 1):\n",
    "                ans += cnt[((x ^ i) << 20) + (y ^ (k - i))]\n",
    "            cnt[(x << 20) + y] += 1\n",
    "        return ans\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, coordinates: List[List[int]], k: int) -> int:\n",
    "        def g(x,y):\n",
    "            return x << 20 | y\n",
    "        \n",
    "        st = [g(i,k-i) for i in range(k+1)]\n",
    "        mp = Counter()\n",
    "        ans = 0\n",
    "        for x, y in coordinates:\n",
    "            t = g(x,y)\n",
    "            if t in mp:\n",
    "                ans += mp[t]\n",
    "            for i in st:\n",
    "                mp[i^t] += 1\n",
    "        return ans\n",
    "            \n",
    "            \n",
    "        \n",
    "                "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, coordinates: List[List[int]], k: int) -> int:\n",
    "        def g(x,y):\n",
    "            return x << 20 | y\n",
    "        \n",
    "        st = {g(i,k-i) for i in range(k+1)}\n",
    "        mp = Counter()\n",
    "        ans = 0\n",
    "        for x, y in coordinates:\n",
    "            t = g(x,y)\n",
    "            if t in mp:\n",
    "                ans += mp[t]\n",
    "            for i in st:\n",
    "                mp[i^t] += 1\n",
    "        return ans\n",
    "            \n",
    "            \n",
    "        \n",
    "                "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, coordinates: List[List[int]], k: int) -> int:\n",
    "        ans = 0\n",
    "        cnt = Counter()\n",
    "        for x, y in coordinates:\n",
    "            for i in range(k+1):\n",
    "                ans += cnt[(x^i, y^(k-i))]\n",
    "            cnt[(x, y)] += 1\n",
    "        return ans"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, coordinates: List[List[int]], k: int) -> int:\n",
    "        num = 0\n",
    "        cnt = Counter()\n",
    "        for x, y in coordinates:\n",
    "            for z in range(k+1):\n",
    "                num += cnt[x ^ z, y ^ (k - z)]\n",
    "            cnt[x, y] += 1\n",
    "        return num"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, coordinates: List[List[int]], k: int) -> int:\n",
    "        ans = 0\n",
    "        cnt = Counter()\n",
    "        for x, y in coordinates:\n",
    "            for i in range(k + 1):\n",
    "                ans += cnt[x ^ i, y ^ (k - i)]  # tuple 的括号可以省略\n",
    "            cnt[x, y] += 1  # tuple 的括号可以省略\n",
    "        return ans\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "from typing import List\n",
    "from collections import defaultdict\n",
    "\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, coordinates: List[List[int]], k: int) -> int:\n",
    "        m = defaultdict(set)\n",
    "        has = set([(a, b) for a, b in coordinates])\n",
    "        for x, y in coordinates:\n",
    "            pass\n",
    "            for a in range(k + 1):\n",
    "                nx = x ^ a\n",
    "                ny = y ^ (k - a)\n",
    "                if (nx, ny) not in has: continue\n",
    "                m[(x, y)].add((nx, ny))\n",
    "\n",
    "        res = 0\n",
    "        count = defaultdict(int)\n",
    "\n",
    "        for info in coordinates:\n",
    "            x1, y1 = info\n",
    "            cur = (x1, y1)\n",
    "\n",
    "            for need in m[cur]:\n",
    "                res += count[need]\n",
    "            count[cur] += 1\n",
    "        return res"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "from typing import List\n",
    "from collections import defaultdict\n",
    "\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, coordinates: List[List[int]], k: int) -> int:\n",
    "        m = defaultdict(set)\n",
    "        has = set([(a, b) for a, b in coordinates])\n",
    "        for x, y in coordinates:\n",
    "            for a in range(k + 1):\n",
    "                nx = x ^ a\n",
    "                ny = y ^ (k - a)\n",
    "                if (nx, ny) not in has: continue\n",
    "                m[(x, y)].add((nx, ny))\n",
    "\n",
    "        res = 0\n",
    "        count = defaultdict(int)\n",
    "\n",
    "        for info in coordinates:\n",
    "            x1, y1 = info\n",
    "            cur = (x1, y1)\n",
    "\n",
    "            for need in m[cur]:\n",
    "                res += count[need]\n",
    "            count[cur] += 1\n",
    "        return res"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, coordinates: List[List[int]], k: int) -> int:\n",
    "        if k == 0:\n",
    "            c = collections.Counter()\n",
    "            for x, y in coordinates:\n",
    "                c[(x, y)] += 1\n",
    "            res = 0\n",
    "            for x in c:\n",
    "                res += c[x] * (c[x] - 1) // 2\n",
    "            return res\n",
    "\n",
    "        c = collections.defaultdict(collections.Counter)\n",
    "        for x, y in coordinates:\n",
    "            c[x][y] += 1\n",
    "        res = 0\n",
    "        for x, y in coordinates:\n",
    "            for i in range(max(0, x - k), x + k + 1):\n",
    "                v = k - (i ^ x)\n",
    "                if v >= 0:\n",
    "                    w = v ^ y\n",
    "                    res += c[i][w]\n",
    "        return res // 2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, coordinates: List[List[int]], k: int) -> int:\n",
    "        prev = defaultdict(dict)\n",
    "        n = len(coordinates)\n",
    "        ans = 0\n",
    "        for i in range(n):\n",
    "            x, y = coordinates[i]\n",
    "            for v in range(k + 1):\n",
    "                t = x ^ v\n",
    "                for (x1, y1), time in prev[t].items():\n",
    "                    if (x1 ^ x) + (y1 ^ y) == k:\n",
    "                        ans += time\n",
    "            if (x, y) not in prev[x]:\n",
    "                prev[x][(x, y)] = 0\n",
    "            prev[x][(x, y)] += 1\n",
    "        return ans"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, coordinates: List[List[int]], k: int) -> int:\n",
    "        d = {}\n",
    "        res = 0\n",
    "        for x,y in coordinates:\n",
    "            for i in range(k+1):\n",
    "                x0,y0 = i,k-i\n",
    "                x1,y1 = x^x0,y^y0\n",
    "                if tuple([x1,y1]) in d:\n",
    "                    res += d[tuple([x1,y1])]\n",
    "            if tuple([x,y]) in d:\n",
    "                d[tuple([x,y])] += 1\n",
    "            else:\n",
    "                d[tuple([x,y])] = 1\n",
    "        return res"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, coordinates: List[List[int]], k: int) -> int:\n",
    "        ans = 0\n",
    "        cnt = Counter()\n",
    "        for x, y in coordinates:\n",
    "            for i in range(k + 1):\n",
    "                ans += cnt[x ^ i, y ^ (k - i)]  # tuple 的括号可以省略\n",
    "            cnt[x, y] += 1  # tuple 的括号可以省略\n",
    "        return ans"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "  def countPairs(self, coordinates: List[List[int]], k: int) -> int:\n",
    "    cnt = Counter()\n",
    "    ans = 0\n",
    "    for x, y in coordinates:\n",
    "      for i in range(k + 1):\n",
    "        x1, y1 = x ^ i, y ^ (k - i)\n",
    "        if (x1, y1) in cnt:\n",
    "          ans += cnt[(x1, y1)]\n",
    "      cnt[(x, y)] += 1\n",
    "    return ans\n",
    "        \n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, coordinates: List[List[int]], k: int) -> int:\n",
    "        d  = defaultdict(int)\n",
    "        for x , y in coordinates:\n",
    "            t = (x, y )\n",
    "            d[t]+=1\n",
    "        ans = 0 \n",
    "        for  v in range(k  +1):\n",
    "            for x, y in d:\n",
    "                nt = ( (x ^ v) , (k - v ) ^ y )\n",
    "                if  nt in d:\n",
    "                    if nt == (x, y ):\n",
    "                        ans+=(d[nt] -  1) *  d[(x,y)]\n",
    "                    else:\n",
    "                        ans +=d[nt] * d[(x,y)]\n",
    "                    \n",
    "        return ans // 2\n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, A: List[List[int]], k: int) -> int:\n",
    "        res, mp = 0, Counter()\n",
    "        for x, y in A:\n",
    "            for i in range(k + 1):\n",
    "                res += mp[x ^ i, y ^ (k - i)]\n",
    "            mp[x, y] += 1\n",
    "        return res"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, coordinates: List[List[int]], k: int) -> int:\n",
    "        mem=Counter()\n",
    "        ans=0\n",
    "        for x,y in coordinates:\n",
    "            ans+=mem[(x,y)]\n",
    "            for i in range(k+1):\n",
    "                mem[(x^i,y^(k-i))]+=1\n",
    "        return ans"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, coordinates: List[List[int]], k: int) -> int:\n",
    "        ans = 0\n",
    "        cnt = Counter()\n",
    "        for x, y in coordinates:\n",
    "            for i in range(k + 1):\n",
    "                ans += cnt[x ^ i, y ^ (k - i)]  # tuple 的括号可以省略\n",
    "            cnt[x, y] += 1  # tuple 的括号可以省略\n",
    "        return ans\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, coordinates: List[List[int]], k: int) -> int:\n",
    "        ans=0\n",
    "        cnt=Counter()\n",
    "        for x,y in coordinates:\n",
    "            for i in range(k+1):\n",
    "                ans+=cnt[x^i, y^(k-i)]\n",
    "            cnt[x,y]+=1\n",
    "        return ans"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, coordinates: List[List[int]], k: int) -> int:\n",
    "        cnt = Counter()\n",
    "        ans = 0\n",
    "        for x, y in coordinates:\n",
    "            for i in range(k + 1):\n",
    "                x1, y1 = x ^ i, y ^ (k - i)\n",
    "                if (x1, y1) in cnt:\n",
    "                    ans += cnt[(x1, y1)]\n",
    "            cnt[(x, y)] += 1\n",
    "        return ans\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "from collections import defaultdict\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, coordinates: List[List[int]], k: int) -> int:\n",
    "\n",
    "        n = len(coordinates)\n",
    "        res = 0\n",
    "        mp = Counter()\n",
    "\n",
    "        for i,[x,y] in enumerate(coordinates):\n",
    "            mp[(x,y)]+=1\n",
    "\n",
    "        for i in range(n):\n",
    "            \n",
    "            x,y = coordinates[i][0],coordinates[i][1]\n",
    "            mp[(x,y)]-=1\n",
    "            mp[(x,y)] = max(0,mp[x,y])\n",
    "            for j in range(k+1):\n",
    "                nx = x^j\n",
    "                ny = (k-j)^y\n",
    "                res+=mp[(nx,ny)]\n",
    "            \n",
    "        return res"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "\n",
    "    def countPairs(self, coordinates: List[List[int]], k: int) -> int:\n",
    "\n",
    "        ans = 0\n",
    "\n",
    "        cnt = Counter()\n",
    "\n",
    "        for x, y in coordinates:\n",
    "\n",
    "            for i in range(k + 1):\n",
    "\n",
    "                ans += cnt[x ^ i, y ^ (k - i)]  # tuple 的括号可以省略\n",
    "\n",
    "            cnt[x, y] += 1  # tuple 的括号可以省略\n",
    "\n",
    "        return ans\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, coordinates: List[List[int]], k: int) -> int:\n",
    "        d=defaultdict(int)\n",
    "        ans=0\n",
    "        for i,j in coordinates:\n",
    "            ans+=d[(i,j)]\n",
    "            for m in range(k+1):\n",
    "                x=m^i\n",
    "                y=(k-m)^j\n",
    "                d[(x,y)]+=1\n",
    "        return ans"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, coordinates: List[List[int]], k: int) -> int:\n",
    "        cnter = defaultdict(int)\n",
    "        result = 0\n",
    "        for x, y in coordinates:\n",
    "            for j in range(k + 1):\n",
    "                x0, y0 = x ^ j, y ^ (k - j)\n",
    "                result += cnter[x0, y0]\n",
    "                # print(x0, y0)\n",
    "            cnter[x, y] += 1\n",
    "        # print(cnter[1, 3])\n",
    "        return result"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, coordinates: List[List[int]], k: int) -> int:\n",
    "        cnt = defaultdict(int)\n",
    "        ans = 0\n",
    "        \n",
    "        searchDiff = []\n",
    "        zeros = []\n",
    "        i = 0\n",
    "        while i <= k:\n",
    "            searchDiff.append([i, k-i])\n",
    "            i += 1\n",
    "        print(searchDiff)\n",
    "        for x, y in coordinates:\n",
    "            for dx, dy in searchDiff:\n",
    "                # tup = \n",
    "                ans += cnt[(x ^ dx, y ^ dy)]\n",
    "                # ans += cnt[(x-dx, y+dy)]\n",
    "                # ans += cnt[(x+dx, y-dy)]\n",
    "                # ans += cnt[(x-dx, y-dy)]\n",
    "            print(x,y, ans)\n",
    "            cnt[(x,y)] += 1\n",
    "        return ans"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, coordinates: List[List[int]], k: int) -> int:\n",
    "        res = 0\n",
    "        cnt = Counter()\n",
    "        for x, y in coordinates:\n",
    "            for i in range(k+1):\n",
    "                res += cnt[x^i, y^(k-i)]\n",
    "            cnt[x, y]+=1\n",
    "        return res"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "\n",
    "    def countPairs(self, coordinates: List[List[int]], k: int) -> int:\n",
    "\n",
    "        cnt = Counter()\n",
    "\n",
    "        ans = 0\n",
    "\n",
    "        for x, y in coordinates:\n",
    "\n",
    "            for i in range(k + 1):\n",
    "\n",
    "                x1, y1 = x ^ i, y ^ (k - i)\n",
    "\n",
    "                if (x1, y1) in cnt:\n",
    "\n",
    "                    ans += cnt[(x1, y1)]\n",
    "\n",
    "            cnt[(x, y)] += 1\n",
    "\n",
    "        return ans\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, coordinates: List[List[int]], k: int) -> int:\n",
    "        ans = 0\n",
    "        cnt = Counter()\n",
    "        for x, y in coordinates:\n",
    "            for i in range(k + 1):\n",
    "                ans += cnt[x ^ i, y ^ (k - i)]\n",
    "            cnt[x, y] += 1\n",
    "        return ans"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "from bisect import bisect_left\n",
    "\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, nums: List[int], target: int) -> int:\n",
    "        nums.sort()\n",
    "        \n",
    "        n_pairs: int = 0\n",
    "        for i in range(len(nums) - 1):\n",
    "            the_other: int = target - nums[i]\n",
    "            if the_other < nums[i]:\n",
    "                break\n",
    "\n",
    "            end: int = bisect_left(nums, the_other, i + 1)\n",
    "            n_pairs += end - i - 1\n",
    "\n",
    "        return n_pairs"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, nums: List[int], target: int) -> int:\n",
    "        sum = 0\n",
    "        for i in range(len(nums)):\n",
    "            for j in range(i+1, len(nums)):\n",
    "                if nums[i]+nums[j]<target:\n",
    "                        sum += 1\n",
    "        return sum\n",
    "\n",
    "                    "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, nums: List[int], target: int) -> int:\n",
    "        nums.sort()\n",
    "        res = 0\n",
    "        l, r = 0, len(nums) - 1\n",
    "        while l<r:\n",
    "            if nums[l]+nums[r]<target:\n",
    "                res+=r-l\n",
    "                l+=1\n",
    "            else:\n",
    "                r-=1\n",
    "        return res"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, nums: List[int], target: int) -> int:\n",
    "        nums.sort()\n",
    "        res = 0\n",
    "        l, r = 0, len(nums) - 1\n",
    "        while l < r:\n",
    "            if nums[l] + nums[r] < target:\n",
    "                res += r - l \n",
    "                l += 1\n",
    "            else:\n",
    "                r -= 1\n",
    "        return res"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "import time\n",
    "from ctypes import *\n",
    "import mmap\n",
    "\n",
    "def translate(s):\n",
    "    res=b''\n",
    "    for l in s.split('\\n'):\n",
    "        if not ':' in l or '>:' in l: continue\n",
    "        l=l[l.find(':')+1:].strip()\n",
    "        l=l[:l.find('   ')].strip()\n",
    "        for b in l.split(' '):\n",
    "            res+=int(b,16).to_bytes(1,byteorder='little')\n",
    "    return res\n",
    "\n",
    "buf=mmap.mmap(-1,mmap.PAGESIZE,prot=mmap.PROT_READ|mmap.PROT_WRITE|mmap.PROT_EXEC)\n",
    "def compile_asm(s,ftype):\n",
    "    buf.write(translate(s))\n",
    "    return ftype(addressof(c_void_p.from_buffer(buf)))\n",
    "\n",
    "'''\n",
    "#include<immintrin.h>\n",
    "#define us unsigned short\n",
    "__attribute__((no_sanitize_address,no_sanitize_memory))\n",
    "__attribute__((target(\"avx512bw\")))\n",
    "int countPairs(us *a, int n, us l, us r) {\n",
    "    const int U=31;\n",
    "    int ans=0,d=0;\n",
    "    __m512i L=_mm512_set1_epi16(l),R=_mm512_set1_epi16(r);\n",
    "    for (int i=1;i<n;++i){\n",
    "        if (a[i]!=a[i-1]){\n",
    "            us x=a[i]; __m512i X=_mm512_set1_epi16(x); d=0;\n",
    "            for (__m512i *I=(__m512i*)a,*end=(__m512i*)(a+(i&~U));I!=end;++I){\n",
    "                __m512i Y=_mm512_xor_si512(X,*I);\n",
    "                d+=__builtin_popcount(_mm512_cmpge_epi16_mask(Y,L)&_mm512_cmple_epi16_mask(Y,R));\n",
    "            }\n",
    "            for (int j=i&~U;j<i;++j){int y=x^a[j]; d+=y>=l&&y<=r;}\n",
    "        }\n",
    "        ans+=d;\n",
    "    }\n",
    "    return ans;\n",
    "}\n",
    "'''\n",
    "asm_xor_in=compile_asm('''\n",
    "0:  83 fe 01                cmp    esi,0x1\n",
    "3:  0f 8e e1 04 00 00       jle    4ea <L13>\n",
    "9:  55                      push   rbp\n",
    "a:  41 89 d1                mov    r9d,edx\n",
    "d:  b8 01 00 00 00          mov    eax,0x1\n",
    "12: 41 89 ca                mov    r10d,ecx\n",
    "15: c4 c1 79 6e e2          vmovd  xmm4,r10d\n",
    "1a: c4 c1 79 6e d1          vmovd  xmm2,r9d\n",
    "1f: 45 31 db                xor    r11d,r11d\n",
    "22: c5 f9 6e d8             vmovd  xmm3,eax\n",
    "26: 62 f2 7d 48 7b f2       vpbroadcastw zmm6,edx\n",
    "2c: 62 f2 7d 48 7b f9       vpbroadcastw zmm7,ecx\n",
    "32: 31 d2                   xor    edx,edx\n",
    "34: 48 89 e5                mov    rbp,rsp\n",
    "37: 41 57                   push   r15\n",
    "39: c4 e2 7d 79 e4          vpbroadcastw ymm4,xmm4\n",
    "3e: c4 e2 7d 79 d2          vpbroadcastw ymm2,xmm2\n",
    "43: 41 56                   push   r14\n",
    "45: c4 e2 7d 79 db          vpbroadcastw ymm3,xmm3\n",
    "4a: 62 72 7d 48 7b d0       vpbroadcastw zmm10,eax\n",
    "50: 41 55                   push   r13\n",
    "52: 41 54                   push   r12\n",
    "54: 53                      push   rbx\n",
    "55: 89 f3                   mov    ebx,esi\n",
    "57: be 01 00 00 00          mov    esi,0x1\n",
    "5c: 48 83 e4 c0             and    rsp,0xffffffffffffffc0\n",
    "60: eb 10                   jmp    72 <L12>\n",
    "0000000000000062 <L3>:\n",
    "62: 48 83 c6 01             add    rsi,0x1\n",
    "66: 41 01 d3                add    r11d,edx\n",
    "69: 48 39 f3                cmp    rbx,rsi\n",
    "6c: 0f 84 39 04 00 00       je     4ab <L30>\n",
    "0000000000000072 <L12>:\n",
    "72: 44 0f b7 34 77          movzx  r14d,WORD PTR [rdi+rsi*2]\n",
    "77: 66 44 3b 74 77 fe       cmp    r14w,WORD PTR [rdi+rsi*2-0x2]\n",
    "7d: 74 e3                   je     62 <L3>\n",
    "7f: 41 89 f0                mov    r8d,esi\n",
    "82: 62 52 7d 48 7b ce       vpbroadcastw zmm9,r14d\n",
    "88: 41 83 e0 e0             and    r8d,0xffffffe0\n",
    "8c: 4d 63 e0                movsxd r12,r8d\n",
    "8f: 4e 8d 2c 67             lea    r13,[rdi+r12*2]\n",
    "93: 4c 39 ef                cmp    rdi,r13\n",
    "96: 0f 84 24 04 00 00       je     4c0 <L14>\n",
    "9c: 62 d1 7d 48 6f c9       vmovdqa32 zmm1,zmm9\n",
    "a2: 48 89 f9                mov    rcx,rdi\n",
    "a5: 31 d2                   xor    edx,edx\n",
    "00000000000000a7 <L5>:\n",
    "a7: 62 f1 75 48 ef 01       vpxord zmm0,zmm1,ZMMWORD PTR [rcx]\n",
    "ad: 48 83 c1 40             add    rcx,0x40\n",
    "b1: 62 f3 fd 48 3f cf 02    vpcmplew k1,zmm0,zmm7\n",
    "b8: 62 f3 fd 49 3f c6 05    vpcmpnltw k0{k1},zmm0,zmm6\n",
    "bf: c5 fb 93 c0             kmovd  eax,k0\n",
    "c3: f3 0f b8 c0             popcnt eax,eax\n",
    "c7: 01 c2                   add    edx,eax\n",
    "c9: 49 39 cd                cmp    r13,rcx\n",
    "cc: 75 d9                   jne    a7 <L5>\n",
    "00000000000000ce <L4>:\n",
    "ce: 41 89 f7                mov    r15d,esi\n",
    "d1: 41 39 f0                cmp    r8d,esi\n",
    "d4: 7d 8c                   jge    62 <L3>\n",
    "d6: 89 f1                   mov    ecx,esi\n",
    "d8: 44 29 c1                sub    ecx,r8d\n",
    "db: 8d 41 ff                lea    eax,[rcx-0x1]\n",
    "de: 83 f8 1e                cmp    eax,0x1e\n",
    "e1: 0f 86 e0 03 00 00       jbe    4c7 <L15>\n",
    "e7: 4c 89 e8                mov    rax,r13\n",
    "ea: 41 89 cd                mov    r13d,ecx\n",
    "ed: c5 f1 ef c9             vpxor  xmm1,xmm1,xmm1\n",
    "f1: 41 c1 ed 05             shr    r13d,0x5\n",
    "f5: 49 c1 e5 06             shl    r13,0x6\n",
    "f9: 49 01 c5                add    r13,rax\n",
    "00000000000000fc <L7>:\n",
    "fc: 62 f1 b5 48 ef 00       vpxorq zmm0,zmm9,ZMMWORD PTR [rax]\n",
    "102:    48 83 c0 40             add    rax,0x40\n",
    "106:    62 f3 c5 48 3e c8 05    vpcmpnltuw k1,zmm7,zmm0\n",
    "10d:    62 f3 cd 49 3e c8 02    vpcmpleuw k1{k1},zmm6,zmm0\n",
    "114:    62 d1 ff c9 6f c2       vmovdqu16 zmm0{k1}{z},zmm10\n",
    "11a:    62 f2 7d 48 33 e8       vpmovzxwd zmm5,ymm0\n",
    "120:    62 f3 fd 48 3b c0 01    vextracti64x4 ymm0,zmm0,0x1\n",
    "127:    62 f1 55 48 fe c9       vpaddd zmm1,zmm5,zmm1\n",
    "12d:    62 f2 7d 48 33 c0       vpmovzxwd zmm0,ymm0\n",
    "133:    62 f1 7d 48 fe c9       vpaddd zmm1,zmm0,zmm1\n",
    "139:    49 39 c5                cmp    r13,rax\n",
    "13c:    75 be                   jne    fc <L7>\n",
    "13e:    c5 fd 6f e9             vmovdqa ymm5,ymm1\n",
    "142:    62 f3 fd 48 3b c9 01    vextracti64x4 ymm1,zmm1,0x1\n",
    "149:    c5 d5 fe e9             vpaddd ymm5,ymm5,ymm1\n",
    "14d:    c4 e3 7d 39 e9 01       vextracti128 xmm1,ymm5,0x1\n",
    "153:    c5 d1 fe c1             vpaddd xmm0,xmm5,xmm1\n",
    "157:    c5 f1 73 d8 08          vpsrldq xmm1,xmm0,0x8\n",
    "15c:    c5 f9 fe c1             vpaddd xmm0,xmm0,xmm1\n",
    "160:    c5 f1 73 d8 04          vpsrldq xmm1,xmm0,0x4\n",
    "165:    c5 f9 fe c1             vpaddd xmm0,xmm0,xmm1\n",
    "169:    c5 f9 7e c0             vmovd  eax,xmm0\n",
    "16d:    01 d0                   add    eax,edx\n",
    "16f:    89 44 24 fc             mov    DWORD PTR [rsp-0x4],eax\n",
    "173:    89 c8                   mov    eax,ecx\n",
    "175:    83 e0 e0                and    eax,0xffffffe0\n",
    "178:    41 01 c0                add    r8d,eax\n",
    "17b:    f6 c1 1f                test   cl,0x1f\n",
    "17e:    0f 84 6c 03 00 00       je     4f0 <L31>\n",
    "184:    29 c1                   sub    ecx,eax\n",
    "186:    44 8d 69 ff             lea    r13d,[rcx-0x1]\n",
    "18a:    41 83 fd 0e             cmp    r13d,0xe\n",
    "18e:    0f 86 4d 03 00 00       jbe    4e1 <L17>\n",
    "0000000000000194 <L32>:\n",
    "194:    4c 01 e0                add    rax,r12\n",
    "197:    c4 c1 79 6e ce          vmovd  xmm1,r14d\n",
    "19c:    c4 e2 7d 79 c9          vpbroadcastw ymm1,xmm1\n",
    "1a1:    c5 f5 ef 0c 47          vpxor  ymm1,ymm1,YMMWORD PTR [rdi+rax*2]\n",
    "1a6:    c4 e2 75 3a c4          vpminuw ymm0,ymm1,ymm4\n",
    "1ab:    c5 f5 75 c0             vpcmpeqw ymm0,ymm1,ymm0\n",
    "1af:    c4 e2 6d 3a c9          vpminuw ymm1,ymm2,ymm1\n",
    "1b4:    c5 ed 75 c9             vpcmpeqw ymm1,ymm2,ymm1\n",
    "1b8:    c5 fd db c1             vpand  ymm0,ymm0,ymm1\n",
    "1bc:    c5 fd db c3             vpand  ymm0,ymm0,ymm3\n",
    "1c0:    c4 e2 7d 33 c8          vpmovzxwd ymm1,xmm0\n",
    "1c5:    c4 e3 7d 39 c0 01       vextracti128 xmm0,ymm0,0x1\n",
    "1cb:    c5 f5 fe cd             vpaddd ymm1,ymm1,ymm5\n",
    "1cf:    c4 e2 7d 33 c0          vpmovzxwd ymm0,xmm0\n",
    "1d4:    c5 fd fe c1             vpaddd ymm0,ymm0,ymm1\n",
    "1d8:    c5 f9 6f c8             vmovdqa xmm1,xmm0\n",
    "1dc:    c4 e3 7d 39 c0 01       vextracti128 xmm0,ymm0,0x1\n",
    "1e2:    c5 f1 fe c0             vpaddd xmm0,xmm1,xmm0\n",
    "1e6:    c5 f1 73 d8 08          vpsrldq xmm1,xmm0,0x8\n",
    "1eb:    c5 f9 fe c1             vpaddd xmm0,xmm0,xmm1\n",
    "1ef:    c5 f1 73 d8 04          vpsrldq xmm1,xmm0,0x4\n",
    "1f4:    c5 f9 fe c1             vpaddd xmm0,xmm0,xmm1\n",
    "1f8:    c5 f9 7e c0             vmovd  eax,xmm0\n",
    "1fc:    01 c2                   add    edx,eax\n",
    "1fe:    89 c8                   mov    eax,ecx\n",
    "200:    83 e0 f0                and    eax,0xfffffff0\n",
    "203:    41 01 c0                add    r8d,eax\n",
    "206:    83 e1 0f                and    ecx,0xf\n",
    "209:    0f 84 53 fe ff ff       je     62 <L3>\n",
    "000000000000020f <L10>:\n",
    "20f:    49 63 c8                movsxd rcx,r8d\n",
    "212:    44 0f b7 24 4f          movzx  r12d,WORD PTR [rdi+rcx*2]\n",
    "217:    48 8d 04 09             lea    rax,[rcx+rcx*1]\n",
    "21b:    45 31 f4                xor    r12d,r14d\n",
    "21e:    44 89 e1                mov    ecx,r12d\n",
    "221:    66 45 39 e2             cmp    r10w,r12w\n",
    "225:    41 0f 93 c4             setae  r12b\n",
    "229:    66 44 39 c9             cmp    cx,r9w\n",
    "22d:    0f 93 c1                setae  cl\n",
    "230:    0f b6 c9                movzx  ecx,cl\n",
    "233:    44 21 e1                and    ecx,r12d\n",
    "236:    01 ca                   add    edx,ecx\n",
    "238:    41 8d 48 01             lea    ecx,[r8+0x1]\n",
    "23c:    44 39 f9                cmp    ecx,r15d\n",
    "23f:    0f 8d 1d fe ff ff       jge    62 <L3>\n",
    "245:    0f b7 4c 07 02          movzx  ecx,WORD PTR [rdi+rax*1+0x2]\n",
    "24a:    44 31 f1                xor    ecx,r14d\n",
    "24d:    66 44 39 c9             cmp    cx,r9w\n",
    "251:    41 0f 93 c4             setae  r12b\n",
    "255:    66 41 39 ca             cmp    r10w,cx\n",
    "259:    0f 93 c1                setae  cl\n",
    "25c:    0f b6 c9                movzx  ecx,cl\n",
    "25f:    44 21 e1                and    ecx,r12d\n",
    "262:    01 ca                   add    edx,ecx\n",
    "264:    41 8d 48 02             lea    ecx,[r8+0x2]\n",
    "268:    44 39 f9                cmp    ecx,r15d\n",
    "26b:    0f 8d f1 fd ff ff       jge    62 <L3>\n",
    "271:    0f b7 4c 07 04          movzx  ecx,WORD PTR [rdi+rax*1+0x4]\n",
    "276:    44 31 f1                xor    ecx,r14d\n",
    "279:    66 41 39 ca             cmp    r10w,cx\n",
    "27d:    41 0f 93 c4             setae  r12b\n",
    "281:    66 44 39 c9             cmp    cx,r9w\n",
    "285:    0f 93 c1                setae  cl\n",
    "288:    0f b6 c9                movzx  ecx,cl\n",
    "28b:    44 21 e1                and    ecx,r12d\n",
    "28e:    01 ca                   add    edx,ecx\n",
    "290:    41 8d 48 03             lea    ecx,[r8+0x3]\n",
    "294:    44 39 f9                cmp    ecx,r15d\n",
    "297:    0f 8d c5 fd ff ff       jge    62 <L3>\n",
    "29d:    0f b7 4c 07 06          movzx  ecx,WORD PTR [rdi+rax*1+0x6]\n",
    "2a2:    44 31 f1                xor    ecx,r14d\n",
    "2a5:    66 41 39 ca             cmp    r10w,cx\n",
    "2a9:    41 0f 93 c4             setae  r12b\n",
    "2ad:    66 44 39 c9             cmp    cx,r9w\n",
    "2b1:    0f 93 c1                setae  cl\n",
    "2b4:    0f b6 c9                movzx  ecx,cl\n",
    "2b7:    44 21 e1                and    ecx,r12d\n",
    "2ba:    01 ca                   add    edx,ecx\n",
    "2bc:    41 8d 48 04             lea    ecx,[r8+0x4]\n",
    "2c0:    44 39 f9                cmp    ecx,r15d\n",
    "2c3:    0f 8d 99 fd ff ff       jge    62 <L3>\n",
    "2c9:    0f b7 4c 07 08          movzx  ecx,WORD PTR [rdi+rax*1+0x8]\n",
    "2ce:    44 31 f1                xor    ecx,r14d\n",
    "2d1:    66 41 39 ca             cmp    r10w,cx\n",
    "2d5:    41 0f 93 c4             setae  r12b\n",
    "2d9:    66 44 39 c9             cmp    cx,r9w\n",
    "2dd:    0f 93 c1                setae  cl\n",
    "2e0:    0f b6 c9                movzx  ecx,cl\n",
    "2e3:    44 21 e1                and    ecx,r12d\n",
    "2e6:    01 ca                   add    edx,ecx\n",
    "2e8:    41 8d 48 05             lea    ecx,[r8+0x5]\n",
    "2ec:    44 39 f9                cmp    ecx,r15d\n",
    "2ef:    0f 8d 6d fd ff ff       jge    62 <L3>\n",
    "2f5:    0f b7 4c 07 0a          movzx  ecx,WORD PTR [rdi+rax*1+0xa]\n",
    "2fa:    44 31 f1                xor    ecx,r14d\n",
    "2fd:    66 41 39 ca             cmp    r10w,cx\n",
    "301:    41 0f 93 c4             setae  r12b\n",
    "305:    66 44 39 c9             cmp    cx,r9w\n",
    "309:    0f 93 c1                setae  cl\n",
    "30c:    0f b6 c9                movzx  ecx,cl\n",
    "30f:    44 21 e1                and    ecx,r12d\n",
    "312:    01 ca                   add    edx,ecx\n",
    "314:    41 8d 48 06             lea    ecx,[r8+0x6]\n",
    "318:    44 39 f9                cmp    ecx,r15d\n",
    "31b:    0f 8d 41 fd ff ff       jge    62 <L3>\n",
    "321:    0f b7 4c 07 0c          movzx  ecx,WORD PTR [rdi+rax*1+0xc]\n",
    "326:    44 31 f1                xor    ecx,r14d\n",
    "329:    66 41 39 ca             cmp    r10w,cx\n",
    "32d:    41 0f 93 c4             setae  r12b\n",
    "331:    66 44 39 c9             cmp    cx,r9w\n",
    "335:    0f 93 c1                setae  cl\n",
    "338:    0f b6 c9                movzx  ecx,cl\n",
    "33b:    44 21 e1                and    ecx,r12d\n",
    "33e:    01 ca                   add    edx,ecx\n",
    "340:    41 8d 48 07             lea    ecx,[r8+0x7]\n",
    "344:    44 39 f9                cmp    ecx,r15d\n",
    "347:    0f 8d 15 fd ff ff       jge    62 <L3>\n",
    "34d:    0f b7 4c 07 0e          movzx  ecx,WORD PTR [rdi+rax*1+0xe]\n",
    "352:    44 31 f1                xor    ecx,r14d\n",
    "355:    66 41 39 ca             cmp    r10w,cx\n",
    "359:    41 0f 93 c4             setae  r12b\n",
    "35d:    66 44 39 c9             cmp    cx,r9w\n",
    "361:    0f 93 c1                setae  cl\n",
    "364:    0f b6 c9                movzx  ecx,cl\n",
    "367:    44 21 e1                and    ecx,r12d\n",
    "36a:    01 ca                   add    edx,ecx\n",
    "36c:    41 8d 48 08             lea    ecx,[r8+0x8]\n",
    "370:    44 39 f9                cmp    ecx,r15d\n",
    "373:    0f 8d e9 fc ff ff       jge    62 <L3>\n",
    "379:    0f b7 4c 07 10          movzx  ecx,WORD PTR [rdi+rax*1+0x10]\n",
    "37e:    44 31 f1                xor    ecx,r14d\n",
    "381:    66 41 39 ca             cmp    r10w,cx\n",
    "385:    41 0f 93 c4             setae  r12b\n",
    "389:    66 44 39 c9             cmp    cx,r9w\n",
    "38d:    0f 93 c1                setae  cl\n",
    "390:    0f b6 c9                movzx  ecx,cl\n",
    "393:    44 21 e1                and    ecx,r12d\n",
    "396:    01 ca                   add    edx,ecx\n",
    "398:    41 8d 48 09             lea    ecx,[r8+0x9]\n",
    "39c:    44 39 f9                cmp    ecx,r15d\n",
    "39f:    0f 8d bd fc ff ff       jge    62 <L3>\n",
    "3a5:    0f b7 4c 07 12          movzx  ecx,WORD PTR [rdi+rax*1+0x12]\n",
    "3aa:    44 31 f1                xor    ecx,r14d\n",
    "3ad:    66 41 39 ca             cmp    r10w,cx\n",
    "3b1:    41 0f 93 c4             setae  r12b\n",
    "3b5:    66 44 39 c9             cmp    cx,r9w\n",
    "3b9:    0f 93 c1                setae  cl\n",
    "3bc:    0f b6 c9                movzx  ecx,cl\n",
    "3bf:    44 21 e1                and    ecx,r12d\n",
    "3c2:    01 ca                   add    edx,ecx\n",
    "3c4:    41 8d 48 0a             lea    ecx,[r8+0xa]\n",
    "3c8:    44 39 f9                cmp    ecx,r15d\n",
    "3cb:    0f 8d 91 fc ff ff       jge    62 <L3>\n",
    "3d1:    0f b7 4c 07 14          movzx  ecx,WORD PTR [rdi+rax*1+0x14]\n",
    "3d6:    44 31 f1                xor    ecx,r14d\n",
    "3d9:    66 41 39 ca             cmp    r10w,cx\n",
    "3dd:    41 0f 93 c4             setae  r12b\n",
    "3e1:    66 44 39 c9             cmp    cx,r9w\n",
    "3e5:    0f 93 c1                setae  cl\n",
    "3e8:    0f b6 c9                movzx  ecx,cl\n",
    "3eb:    44 21 e1                and    ecx,r12d\n",
    "3ee:    01 ca                   add    edx,ecx\n",
    "3f0:    41 8d 48 0b             lea    ecx,[r8+0xb]\n",
    "3f4:    44 39 f9                cmp    ecx,r15d\n",
    "3f7:    0f 8d 65 fc ff ff       jge    62 <L3>\n",
    "3fd:    0f b7 4c 07 16          movzx  ecx,WORD PTR [rdi+rax*1+0x16]\n",
    "402:    44 31 f1                xor    ecx,r14d\n",
    "405:    66 41 39 ca             cmp    r10w,cx\n",
    "409:    41 0f 93 c4             setae  r12b\n",
    "40d:    66 44 39 c9             cmp    cx,r9w\n",
    "411:    0f 93 c1                setae  cl\n",
    "414:    0f b6 c9                movzx  ecx,cl\n",
    "417:    44 21 e1                and    ecx,r12d\n",
    "41a:    01 ca                   add    edx,ecx\n",
    "41c:    41 8d 48 0c             lea    ecx,[r8+0xc]\n",
    "420:    44 39 f9                cmp    ecx,r15d\n",
    "423:    0f 8d 39 fc ff ff       jge    62 <L3>\n",
    "429:    0f b7 4c 07 18          movzx  ecx,WORD PTR [rdi+rax*1+0x18]\n",
    "42e:    44 31 f1                xor    ecx,r14d\n",
    "431:    66 41 39 ca             cmp    r10w,cx\n",
    "435:    41 0f 93 c4             setae  r12b\n",
    "439:    66 44 39 c9             cmp    cx,r9w\n",
    "43d:    0f 93 c1                setae  cl\n",
    "440:    0f b6 c9                movzx  ecx,cl\n",
    "443:    44 21 e1                and    ecx,r12d\n",
    "446:    01 ca                   add    edx,ecx\n",
    "448:    41 8d 48 0d             lea    ecx,[r8+0xd]\n",
    "44c:    44 39 f9                cmp    ecx,r15d\n",
    "44f:    0f 8d 0d fc ff ff       jge    62 <L3>\n",
    "455:    0f b7 4c 07 1a          movzx  ecx,WORD PTR [rdi+rax*1+0x1a]\n",
    "45a:    44 31 f1                xor    ecx,r14d\n",
    "45d:    66 41 39 ca             cmp    r10w,cx\n",
    "461:    41 0f 93 c4             setae  r12b\n",
    "465:    66 44 39 c9             cmp    cx,r9w\n",
    "469:    0f 93 c1                setae  cl\n",
    "46c:    41 83 c0 0e             add    r8d,0xe\n",
    "470:    0f b6 c9                movzx  ecx,cl\n",
    "473:    44 21 e1                and    ecx,r12d\n",
    "476:    01 ca                   add    edx,ecx\n",
    "478:    45 39 f8                cmp    r8d,r15d\n",
    "47b:    0f 8d e1 fb ff ff       jge    62 <L3>\n",
    "481:    66 44 33 74 07 1c       xor    r14w,WORD PTR [rdi+rax*1+0x1c]\n",
    "487:    66 45 39 f2             cmp    r10w,r14w\n",
    "48b:    0f 93 c1                setae  cl\n",
    "48e:    31 c0                   xor    eax,eax\n",
    "490:    66 45 39 ce             cmp    r14w,r9w\n",
    "494:    0f 93 c0                setae  al\n",
    "497:    48 83 c6 01             add    rsi,0x1\n",
    "49b:    21 c8                   and    eax,ecx\n",
    "49d:    01 c2                   add    edx,eax\n",
    "49f:    41 01 d3                add    r11d,edx\n",
    "4a2:    48 39 f3                cmp    rbx,rsi\n",
    "4a5:    0f 85 c7 fb ff ff       jne    72 <L12>\n",
    "00000000000004ab <L30>:\n",
    "4ab:    c5 f8 77                vzeroupper\n",
    "4ae:    48 8d 65 d8             lea    rsp,[rbp-0x28]\n",
    "4b2:    44 89 d8                mov    eax,r11d\n",
    "4b5:    5b                      pop    rbx\n",
    "4b6:    41 5c                   pop    r12\n",
    "4b8:    41 5d                   pop    r13\n",
    "4ba:    41 5e                   pop    r14\n",
    "4bc:    41 5f                   pop    r15\n",
    "4be:    5d                      pop    rbp\n",
    "4bf:    c3                      ret\n",
    "00000000000004c0 <L14>:\n",
    "4c0:    31 d2                   xor    edx,edx\n",
    "4c2:    e9 07 fc ff ff          jmp    ce <L4>\n",
    "00000000000004c7 <L15>:\n",
    "4c7:    31 c0                   xor    eax,eax\n",
    "4c9:    89 54 24 fc             mov    DWORD PTR [rsp-0x4],edx\n",
    "4cd:    c5 d1 ef ed             vpxor  xmm5,xmm5,xmm5\n",
    "4d1:    29 c1                   sub    ecx,eax\n",
    "4d3:    44 8d 69 ff             lea    r13d,[rcx-0x1]\n",
    "4d7:    41 83 fd 0e             cmp    r13d,0xe\n",
    "4db:    0f 87 b3 fc ff ff       ja     194 <L32>\n",
    "00000000000004e1 <L17>:\n",
    "4e1:    8b 54 24 fc             mov    edx,DWORD PTR [rsp-0x4]\n",
    "4e5:    e9 25 fd ff ff          jmp    20f <L10>\n",
    "00000000000004ea <L13>:\n",
    "4ea:    31 c0                   xor    eax,eax\n",
    "4ec:    c5 f8 77                vzeroupper\n",
    "4ef:    c3                      ret\n",
    "00000000000004f0 <L31>:\n",
    "4f0:    8b 54 24 fc             mov    edx,DWORD PTR [rsp-0x4]\n",
    "4f4:    e9 69 fb ff ff          jmp    62 <L3>\n",
    "''',CFUNCTYPE(c_int,POINTER(c_ushort),c_int,c_ushort,c_ushort))\n",
    "\n",
    "asm_sort=compile_asm('''\n",
    "0000000000000000 <Qsort>:\n",
    "0:  41 56                   push   r14\n",
    "2:  48 63 c6                movsxd rax,esi\n",
    "5:  49 89 fe                mov    r14,rdi\n",
    "8:  41 89 d3                mov    r11d,edx\n",
    "b:  41 55                   push   r13\n",
    "d:  4c 8d 2c 47             lea    r13,[rdi+rax*2]\n",
    "11: 41 54                   push   r12\n",
    "13: 44 8d 60 01             lea    r12d,[rax+0x1]\n",
    "17: 55                      push   rbp\n",
    "18: 48 89 c5                mov    rbp,rax\n",
    "1b: 53                      push   rbx\n",
    "000000000000001c <L8>:\n",
    "1c: 42 8d 44 1d 00          lea    eax,[rbp+r11*1+0x0]\n",
    "21: 41 89 e8                mov    r8d,ebp\n",
    "24: 45 89 e1                mov    r9d,r12d\n",
    "27: 4c 89 ef                mov    rdi,r13\n",
    "2a: d1 f8                   sar    eax,1\n",
    "2c: 44 89 db                mov    ebx,r11d\n",
    "2f: 48 98                   cdqe\n",
    "31: 41 0f b7 34 46          movzx  esi,WORD PTR [r14+rax*2]\n",
    "36: 49 63 c3                movsxd rax,r11d\n",
    "0000000000000039 <L2>:\n",
    "39: 44 0f b7 17             movzx  r10d,WORD PTR [rdi]\n",
    "3d: 49 8d 0c 46             lea    rcx,[r14+rax*2]\n",
    "41: 0f b7 11                movzx  edx,WORD PTR [rcx]\n",
    "44: 66 41 39 f2             cmp    r10w,si\n",
    "48: 72 47                   jb     91 <L3>\n",
    "4a: 66 39 d6                cmp    si,dx\n",
    "4d: 73 17                   jae    66 <L4>\n",
    "4f: 49 8d 44 46 fe          lea    rax,[r14+rax*2-0x2]\n",
    "0000000000000054 <L5>:\n",
    "54: 48 89 c1                mov    rcx,rax\n",
    "57: 0f b7 10                movzx  edx,WORD PTR [rax]\n",
    "5a: 48 83 e8 02             sub    rax,0x2\n",
    "5e: 83 eb 01                sub    ebx,0x1\n",
    "61: 66 39 d6                cmp    si,dx\n",
    "64: 72 ee                   jb     54 <L5>\n",
    "0000000000000066 <L4>:\n",
    "66: 44 89 c0                mov    eax,r8d\n",
    "69: 41 39 d8                cmp    r8d,ebx\n",
    "6c: 7e 0e                   jle    7c <L14>\n",
    "000000000000006e <L6>:\n",
    "6e: 41 39 c3                cmp    r11d,eax\n",
    "71: 7f 35                   jg     a8 <L15>\n",
    "0000000000000073 <L7>:\n",
    "73: 39 dd                   cmp    ebp,ebx\n",
    "75: 7d 28                   jge    9f <L16>\n",
    "77: 41 89 db                mov    r11d,ebx\n",
    "7a: eb a0                   jmp    1c <L8>\n",
    "000000000000007c <L14>:\n",
    "7c: 83 eb 01                sub    ebx,0x1\n",
    "7f: 66 89 17                mov    WORD PTR [rdi],dx\n",
    "82: 44 89 c8                mov    eax,r9d\n",
    "85: 66 44 89 11             mov    WORD PTR [rcx],r10w\n",
    "89: 41 39 d9                cmp    r9d,ebx\n",
    "8c: 7f e0                   jg     6e <L6>\n",
    "8e: 48 63 c3                movsxd rax,ebx\n",
    "0000000000000091 <L3>:\n",
    "91: 48 83 c7 02             add    rdi,0x2\n",
    "95: 41 83 c1 01             add    r9d,0x1\n",
    "99: 41 83 c0 01             add    r8d,0x1\n",
    "9d: eb 9a                   jmp    39 <L2>\n",
    "000000000000009f <L16>:\n",
    "9f: 5b                      pop    rbx\n",
    "a0: 5d                      pop    rbp\n",
    "a1: 41 5c                   pop    r12\n",
    "a3: 41 5d                   pop    r13\n",
    "a5: 41 5e                   pop    r14\n",
    "a7: c3                      ret\n",
    "00000000000000a8 <L15>:\n",
    "a8: 44 89 da                mov    edx,r11d\n",
    "ab: 89 c6                   mov    esi,eax\n",
    "ad: 4c 89 f7                mov    rdi,r14\n",
    "b0: e8 4b ff ff ff          call   0 <Qsort>\n",
    "b5: eb bc                   jmp    73 <L7>\n",
    "''',CFUNCTYPE(c_int,POINTER(c_ushort),c_int,c_int))\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, nums: List[int], l: int, r: int) -> int:\n",
    "        n,ans=len(nums),0\n",
    "        a=(c_ushort*n)(*nums)\n",
    "        asm_sort(a,0,n-1)\n",
    "        return asm_xor_in(a,n,l,r)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, nums: List[int], low: int, high: int) -> int:\n",
    "        ans, cnt = 0, Counter(nums)\n",
    "        high += 1\n",
    "        while high:\n",
    "            nxt = Counter()\n",
    "            for x, c in cnt.items():\n",
    "                if high & 1: ans += c * cnt[x ^ (high - 1)]\n",
    "                if low & 1: ans -= c * cnt[x ^ (low - 1)]\n",
    "                nxt[x >> 1] += c\n",
    "            cnt = nxt\n",
    "            low >>= 1\n",
    "            high >>= 1\n",
    "        return ans // 2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, nums: List[int], low: int, high: int) -> int:\n",
    "        ans, cnt = 0, Counter(nums)\n",
    "        high += 1\n",
    "        while high:\n",
    "            nxt = Counter()\n",
    "            for x, c in cnt.items():\n",
    "                if high & 1: ans += c * cnt[x ^ (high - 1)]\n",
    "                if low & 1:  ans -= c * cnt[x ^ (low - 1)]\n",
    "                nxt[x >> 1] += c\n",
    "            cnt = nxt\n",
    "            low >>= 1\n",
    "            high >>= 1\n",
    "        return ans // 2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, nums: List[int], low: int, high: int) -> int:\n",
    "        ans, cnt = 0, Counter(nums)\n",
    "        high += 1\n",
    "        while high:\n",
    "            nxt = Counter()\n",
    "            for x, c in cnt.items():\n",
    "                if high & 1: ans += c * cnt[x ^ (high - 1)]\n",
    "                if low & 1:  ans -= c * cnt[x ^ (low - 1)]\n",
    "                nxt[x >> 1] += c\n",
    "            cnt = nxt\n",
    "            low >>= 1\n",
    "            high >>= 1\n",
    "        return ans // 2\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "from collections import Counter\n",
    "from typing import List\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, nums: List[int], low: int, high: int) -> int:\n",
    "        # 初始化答案为0和计数器\n",
    "        answer, counter = 0, Counter(nums)\n",
    "        \n",
    "        # 调整high以包括其自身在内\n",
    "        high += 1\n",
    "        \n",
    "        # 进行位操作遍历\n",
    "        while high:\n",
    "            next_counter = Counter()\n",
    "            \n",
    "            # 遍历当前的计数器\n",
    "            for num, count in counter.items():\n",
    "                \n",
    "                # 更新答案\n",
    "                if high & 1: \n",
    "                    answer += count * counter[num ^ (high - 1)]\n",
    "                if low & 1:  \n",
    "                    answer -= count * counter[num ^ (low - 1)]\n",
    "                \n",
    "                # 更新下一个计数器\n",
    "                next_counter[num >> 1] += count\n",
    "            \n",
    "            # 更新当前计数器和low、high的值\n",
    "            counter = next_counter\n",
    "            low >>= 1\n",
    "            high >>= 1\n",
    "        \n",
    "        # 最终答案需要除以2\n",
    "        return answer // 2\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, nums: List[int], low: int, high: int) -> int:\n",
    "        ans, cnt = 0, Counter(nums)\n",
    "        high += 1\n",
    "        while high:\n",
    "            nxt = Counter()\n",
    "            for x, c in cnt.items():\n",
    "                if high & 1: ans += c * cnt[x ^ (high - 1)]\n",
    "                if low & 1:  ans -= c * cnt[x ^ (low - 1)]\n",
    "                nxt[x >> 1] += c\n",
    "            cnt = nxt\n",
    "            low >>= 1\n",
    "            high >>= 1\n",
    "        return ans // 2\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, nums: List[int], low: int, high: int) -> int:\n",
    "        ans = 0\n",
    "        cnt = Counter(nums)\n",
    "        high += 1\n",
    "        while high > 0:\n",
    "            agg = Counter()\n",
    "            for num, c in cnt.items():\n",
    "                if (high & 1):\n",
    "                    ans += c * cnt[num ^ (high - 1)]\n",
    "                if (low & 1):\n",
    "                    ans -= c * cnt[num ^ (low - 1)]\n",
    "                agg[num >> 1] += c\n",
    "            high >>= 1\n",
    "            low >>= 1\n",
    "            cnt = agg\n",
    "        return ans >> 1\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class BinaryTrie:\n",
    "    def __init__(self, max_bit: int = 30):\n",
    "        self.inf = 1 << 63\n",
    "        self.to = [[-1], [-1]]\n",
    "        self.cnt = [0]\n",
    "        self.max_bit = max_bit\n",
    "\n",
    "    def add(self, num: int) -> None:\n",
    "        cur = 0\n",
    "        #self.cnt[cur] += 1\n",
    "        for k in range(self.max_bit, -1, -1):\n",
    "            bit = (num >> k) & 1\n",
    "            if self.to[bit][cur] == -1:\n",
    "                self.to[bit][cur] = len(self.cnt)\n",
    "                self.to[0].append(-1)\n",
    "                self.to[1].append(-1)\n",
    "                self.cnt.append(0)\n",
    "            cur = self.to[bit][cur]\n",
    "            self.cnt[cur] += 1\n",
    "\n",
    "    def remove(self, num: int) -> bool:\n",
    "        if self.cnt[0] == 0: return False\n",
    "        cur = 0\n",
    "        rm = [0]\n",
    "        for k in range(self.max_bit, -1, -1):\n",
    "            bit = (num >> k) & 1\n",
    "            cur = self.to[bit][cur]\n",
    "            if cur == -1 or self.cnt[cur] == 0: return False\n",
    "            rm.append(cur)\n",
    "        for cur in rm: self.cnt[cur] -= 1\n",
    "        return True\n",
    "\n",
    "    def count(self, num: int) -> int:\n",
    "        cur = 0\n",
    "        for k in range(self.max_bit, -1, -1):\n",
    "            bit = (num >> k) & 1\n",
    "            cur = self.to[bit][cur]\n",
    "            if cur == -1 or self.cnt[cur] == 0: return 0\n",
    "        return self.cnt[cur]\n",
    "\n",
    "    # 求与num异或严格小于limit的数量\n",
    "    def count_limit_xor(self, num: int, limit: int) -> int:\n",
    "        res = cur = 0\n",
    "        to, cnt = self.to, self.cnt\n",
    "        for k in range(self.max_bit, -1, -1):\n",
    "            bit = (num >> k) & 1\n",
    "            if limit >> k & 1:\n",
    "                if to[bit][cur] != -1:\n",
    "                    res += cnt[to[bit][cur]]\n",
    "                if to[bit ^ 1][cur] == -1 or cnt[to[bit ^ 1][cur]] == 0:\n",
    "                    return res\n",
    "                cur = to[bit ^ 1][cur]\n",
    "            else:\n",
    "                if to[bit][cur] == -1 or cnt[to[bit][cur]] == 0:\n",
    "                    return res\n",
    "                cur = to[bit][cur]\n",
    "        return res\n",
    "\n",
    "    # Get max result for constant x ^ element in array\n",
    "    def max_xor(self, x: int) -> int:\n",
    "        if self.cnt[0] == 0: return -self.inf\n",
    "        res = cur = 0\n",
    "        for k in range(self.max_bit, -1, -1):\n",
    "            bit = (x >> k) & 1\n",
    "            nxt = self.to[bit ^ 1][cur]\n",
    "            if nxt == -1 or self.cnt[nxt] == 0:\n",
    "                cur = self.to[bit][cur]\n",
    "            else:\n",
    "                cur = nxt\n",
    "                res |= 1 << k\n",
    "        return res\n",
    "\n",
    "    # Get min result for constant x ^ element in array\n",
    "    def min_xor(self, x: int) -> int:\n",
    "        if self.cnt[0] == 0: return self.inf\n",
    "        res = cur = 0\n",
    "        for k in range(self.max_bit, -1, -1):\n",
    "            bit = (x >> k) & 1\n",
    "            nxt = self.to[bit][cur]\n",
    "            if nxt == -1 or self.cnt[nxt] == 0:\n",
    "                res |= 1 << k\n",
    "                cur = self.to[bit ^ 1][cur]\n",
    "            else:\n",
    "                cur = nxt\n",
    "        return res\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, nums: List[int], low: int, high: int) -> int:\n",
    "        trie = BinaryTrie(15)\n",
    "        res = 0\n",
    "        n = len(nums)\n",
    "        for x in nums:\n",
    "            res += trie.count_limit_xor(x, high + 1) - trie.count_limit_xor(x, low)\n",
    "            trie.add(x)\n",
    "        return res"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "HIGH_BIT = 15\n",
    "\n",
    "class Trie:\n",
    "    __slots__ = 'children', 'cnt'\n",
    "\n",
    "    def __init__(self):\n",
    "        self.children = [None] * 2\n",
    "        # 经过当前节点的数的数量\n",
    "        self.cnt = 0\n",
    "\n",
    "    def insert(self, x):\n",
    "        '''将数字 x 按照二进制位从高到低的顺序插入到字典树中'''\n",
    "        node = self\n",
    "        for i in range(HIGH_BIT, -1, -1):\n",
    "            v = x >> i & 1\n",
    "            if node.children[v] is None:\n",
    "                node.children[v] = Trie()\n",
    "            node = node.children[v]\n",
    "            node.cnt += 1\n",
    "\n",
    "    def searchXOr(self, x, limit):\n",
    "        '''在字典树中查找与数字 x 的异或值小于 limit 的数量'''\n",
    "        node = self\n",
    "        ans = 0\n",
    "        for i in range(HIGH_BIT, -1, -1):\n",
    "            if node is None:\n",
    "                return ans\n",
    "            v = x >> i & 1\n",
    "            if limit >> i & 1:\n",
    "                if node.children[v]:\n",
    "                    ans += node.children[v].cnt\n",
    "                node = node.children[v ^ 1]\n",
    "            else:\n",
    "                node = node.children[v]\n",
    "\n",
    "        return ans\n",
    "\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, nums: List[int], low: int, high: int) -> int:\n",
    "        t = Trie()\n",
    "        ans = 0\n",
    "        for num in nums:\n",
    "            ans += t.searchXOr(num, high + 1) - t.searchXOr(num, low)\n",
    "            t.insert(num)\n",
    "\n",
    "        return ans"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Trie :\n",
    "    __slots__ = (\"children\",\"cnt\",)\n",
    "\n",
    "    def __init__(self) :\n",
    "        self.children = [None] * 2 \n",
    "        self.cnt = 0\n",
    "    def insert(self , x) :\n",
    "        node = self \n",
    "        for i in range(15 , -1 , -1) :\n",
    "            u = x >> i & 1 \n",
    "            if node.children[u] is None :\n",
    "                node.children[u] = Trie()\n",
    "            node = node.children[u]\n",
    "            node.cnt += 1 \n",
    "    def search(self , x , limit) :\n",
    "        node , ans = self , 0 \n",
    "        for i in range(15 , -1 , -1 ):\n",
    "            if node is None :\n",
    "                return ans \n",
    "            u = x >> i & 1 \n",
    "            if limit >> i & 1 :\n",
    "                if node.children[u] :\n",
    "                    ans += node.children[u].cnt\n",
    "                node = node.children[u ^ 1]\n",
    "            else :\n",
    "                node = node.children[u]\n",
    "        return ans \n",
    "class Solution:\n",
    "    def countPairs(self, nums: List[int], low: int, high: int) -> int:\n",
    "        ans = 0 \n",
    "        tree = Trie()\n",
    "        for x in nums :\n",
    "            ans += tree.search(x , high + 1) - tree.search(x , low)\n",
    "            tree.insert(x)\n",
    "        return ans"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Trie:\n",
    "    __slots__ = 'children', 'cnt', 'high_bit'\n",
    "\n",
    "    def __init__(self):\n",
    "        self.children = [None] * 2\n",
    "        # 经过当前节点的数的数量\n",
    "        self.cnt = 0\n",
    "        # 给定数据范围的最高二进制位数\n",
    "        self.high_bit = 15\n",
    "\n",
    "    def insert(self, x):\n",
    "        '''将数字 x 按照二进制位从高到低的顺序插入到字典树中'''\n",
    "        node = self\n",
    "        for i in range(self.high_bit, -1, -1):\n",
    "            v = x >> i & 1\n",
    "            if node.children[v] is None:\n",
    "                node.children[v] = Trie()\n",
    "            node = node.children[v]\n",
    "            node.cnt += 1\n",
    "\n",
    "    def searchXOr(self, x, limit):\n",
    "        '''在字典树中查找与数字 x 的异或值小于 limit 的数量'''\n",
    "        node = self\n",
    "        ans = 0\n",
    "        for i in range(self.high_bit, -1, -1):\n",
    "            if node is None:\n",
    "                return ans\n",
    "            v = x >> i & 1\n",
    "            if limit >> i & 1:\n",
    "                if node.children[v]:\n",
    "                    ans += node.children[v].cnt\n",
    "                node = node.children[v ^ 1]\n",
    "            else:\n",
    "                node = node.children[v]\n",
    "\n",
    "        return ans\n",
    "\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, nums: List[int], low: int, high: int) -> int:\n",
    "        t = Trie()\n",
    "        ans = 0\n",
    "        for num in nums:\n",
    "            ans += t.searchXOr(num, high + 1) - t.searchXOr(num, low)\n",
    "            t.insert(num)\n",
    "\n",
    "        return ans"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class TreeNode:\n",
    "    def __init__(self):\n",
    "        self.cnt = 0\n",
    "        self.left = None\n",
    "        self.right = None\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, nums: List[int], low: int, high: int) -> int:\n",
    "        root = TreeNode()\n",
    "\n",
    "        def add(num):\n",
    "            node = root\n",
    "            for i in range(15,-1,-1):\n",
    "                if num >> i & 1:\n",
    "                    if not node.right:\n",
    "                        node.right = TreeNode()\n",
    "                    node.right.cnt += 1\n",
    "                    node = node.right\n",
    "                else:\n",
    "                    if not node.left:\n",
    "                        node.left = TreeNode()\n",
    "                    node.left.cnt += 1\n",
    "                    node = node.left\n",
    "\n",
    "        def find(num,target):\n",
    "            node = root\n",
    "            res = 0\n",
    "            for i in range(15,-1,-1):\n",
    "                if target >> i & 1:\n",
    "                    if num >> i & 1:\n",
    "                        if node.right:\n",
    "                            res += node.right.cnt\n",
    "                        if node.left:\n",
    "                            node = node.left\n",
    "                        else:\n",
    "                            return res\n",
    "                    else:\n",
    "                        if node.left:\n",
    "                            res += node.left.cnt\n",
    "                        if node.right:\n",
    "                            node = node.right\n",
    "                        else:\n",
    "                            return res\n",
    "                else:\n",
    "                    if num >> i & 1:\n",
    "                        if node.right:\n",
    "                            node = node.right\n",
    "                        else:\n",
    "                            return res\n",
    "                    else:\n",
    "                        if node.left:\n",
    "                            node = node.left\n",
    "                        else:\n",
    "                            return res\n",
    "            return res\n",
    "        \n",
    "        ans = 0\n",
    "        for num in nums:\n",
    "            l = find(num,low)\n",
    "            h = find(num, high+1)\n",
    "            ans += h-l\n",
    "            add(num)\n",
    "        return ans\n",
    "\n",
    "\n",
    "\n",
    "                    \n",
    "\n",
    "\n",
    "                \n",
    "\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Trie:\n",
    "    def __init__(self):\n",
    "        self.children = [None] * 2\n",
    "        # 经过当前节点的数的数量\n",
    "        self.cnt = 0\n",
    "        # 给定数据范围的最高二进制位数\n",
    "        self.high_bit = 15\n",
    "\n",
    "    def insert(self, x):\n",
    "        '''\n",
    "        将数字 x 按照二进制位从高到低的顺序插入到字典树中\n",
    "        '''\n",
    "        node = self\n",
    "        for i in range(self.high_bit, -1, -1):\n",
    "            v = x >> i & 1\n",
    "            if node.children[v] is None:\n",
    "                node.children[v] = Trie()\n",
    "\n",
    "            node = node.children[v]\n",
    "            node.cnt += 1\n",
    "\n",
    "    def searchXOr(self, x, limit):\n",
    "        '''\n",
    "        在字典树中查找与数字 x 的异或值小于 limit 的数量\n",
    "        '''\n",
    "        node = self\n",
    "        ans = 0\n",
    "        for i in range(self.high_bit, -1, -1):\n",
    "            if node is None:\n",
    "                return ans\n",
    "            v = x >> i & 1\n",
    "            if limit >> i & 1:\n",
    "                if node.children[v]:\n",
    "                    ans += node.children[v].cnt\n",
    "                node = node.children[v ^ 1]\n",
    "            else:\n",
    "                node = node.children[v]\n",
    "\n",
    "        return ans\n",
    "\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, nums: List[int], low: int, high: int) -> int:\n",
    "        t = Trie()\n",
    "        ans = 0\n",
    "        for num in nums:\n",
    "            ans += t.searchXOr(num, high + 1) - t.searchXOr(num, low)\n",
    "            t.insert(num)\n",
    "\n",
    "        return ans"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Trie:\n",
    "    def __init__(self):        \n",
    "        self.child = [None, None]\n",
    "        self.count = 0\n",
    "    \n",
    "class Solution:\n",
    "    def countPairs(self, nums: List[int], low: int, high: int) -> int:\n",
    "        def insert(root: Optional[Trie], n: int) -> NoReturn:\n",
    "            for i in range(15, -1, -1):\n",
    "                x = bool((n) & (1 << i))\n",
    "                if not root.child[x]:\n",
    "                    root.child[x] = Trie()\n",
    "                root.child[x].count += 1\n",
    "                root = root.child[x]\n",
    "\n",
    "        def count_k(root: Optional[Trie], n: int, k: int) -> int:\n",
    "            result = 0\n",
    "            for i in range(15, -1, -1):       \n",
    "                if not root:\n",
    "                    break                       \n",
    "                x = bool(n & (1 << i))\n",
    "                y = k & (1 << i)\n",
    "                if y:\n",
    "                    if root.child[x]:\n",
    "                        result += root.child[x].count\n",
    "                    root = root.child[1 - x]\n",
    "                else:\n",
    "                    root = root.child[x]\n",
    "            return result\n",
    "        root = Trie()\n",
    "        result = 0\n",
    "        for num in nums:\n",
    "            result += count_k(root, num, high + 1) - count_k(root, num, low)\n",
    "            insert(root, num)\n",
    "        return result"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class tr_node:\n",
    "    def __init__(self):\n",
    "        self.ch=[None,None]\n",
    "        self.sum=0\n",
    "        self.val=0\n",
    "class trie_01:\n",
    "    def __init__(self,HIGH_BIT):\n",
    "        self.root=tr_node()\n",
    "        self.HIGH_BIT=HIGH_BIT\n",
    "    def ins(self,x:int):\n",
    "        u=self.root\n",
    "        for i in range(self.HIGH_BIT,-1,-1):\n",
    "            bit=x>>i&1\n",
    "            if not u.ch[bit]:\n",
    "                u.ch[bit]=tr_node()\n",
    "            u=u.ch[bit]\n",
    "            u.sum+=1\n",
    "        u.val=x\n",
    "    def delete(self,x:int):\n",
    "        u=self.root\n",
    "        for i in range(self.HIGH_BIT,-1,-1):\n",
    "            bit=x>>i&1\n",
    "            if not u.ch[bit]:return\n",
    "            u=u.ch[bit]\n",
    "            u.sum-=1\n",
    "    def max_xor(self,x:int)->int:#最大异或\n",
    "        u=self.root\n",
    "        for i in range(self.HIGH_BIT,-1,-1):\n",
    "            bit=x>>i&1\n",
    "            if u.ch[bit^1]:\n",
    "                u=u.ch[bit^1]\n",
    "            else:u=u.ch[bit]\n",
    "        return x^u.val\n",
    "    def less_xor(self,x:int,k:int)->int:\n",
    "        u=self.root\n",
    "        ans=0\n",
    "        for i in range(self.HIGH_BIT,-1,-1):\n",
    "            bit=x>>i&1\n",
    "            if k>>i&1==1:\n",
    "                if u.ch[bit]:ans+=u.ch[bit].sum\n",
    "                if not u.ch[bit^1]:return ans\n",
    "                u=u.ch[bit^1]\n",
    "            else:\n",
    "                if not u.ch[bit]:return ans\n",
    "                u=u.ch[bit]\n",
    "        ans+=u.sum\n",
    "        return ans\n",
    "            \n",
    "class Solution:\n",
    "    def countPairs(self, nums: List[int], low: int, high: int) -> int:\n",
    "        ans=0\n",
    "        n=len(nums)\n",
    "        tr=trie_01(24)\n",
    "        for i in nums:\n",
    "            ans+=tr.less_xor(i,high)-tr.less_xor(i,low-1)\n",
    "            tr.ins(i)\n",
    "        return ans\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Trie:\n",
    "    def __init__(self):        \n",
    "        self.child = [None, None]\n",
    "        self.count = 0\n",
    "    \n",
    "class Solution:\n",
    "    def countPairs(self, nums: List[int], low: int, high: int) -> int:\n",
    "        def insert(root: Optional[Trie], n: int) -> NoReturn:\n",
    "            for i in range(15, -1, -1):\n",
    "                x = bool((n) & (1 << i))\n",
    "                if not root.child[x]:\n",
    "                    root.child[x] = Trie()\n",
    "                root.child[x].count += 1\n",
    "                root = root.child[x]\n",
    "\n",
    "        def helper(root: Optional[Trie], cur: int, x: int) -> int:\n",
    "            result = 0\n",
    "            for i in range(15, -1, -1):       \n",
    "                if not root:\n",
    "                    break                       \n",
    "                k = bool(cur & (1 << i))\n",
    "                if x & (1 << i):\n",
    "                    if root.child[k]:\n",
    "                        result += root.child[k].count\n",
    "                    root = root.child[1 - k]\n",
    "                else:\n",
    "                    root = root.child[k]\n",
    "            return result\n",
    "        root = Trie()\n",
    "        result = 0\n",
    "        for num in nums:\n",
    "            result += helper(root, num, high + 1) - helper(root, num, low)\n",
    "            insert(root, num)\n",
    "        return result"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "\n",
    "class tr_node():\n",
    "    def __init__(self):\n",
    "        self.bit=[None,None]\n",
    "        self.sum=0\n",
    "class trie_01():\n",
    "    def __init__(self):\n",
    "        self.root=tr_node()\n",
    "    def insert(self,x):\n",
    "        u=self.root\n",
    "        i=24\n",
    "        while i>=0:\n",
    "            k=x>>i&1\n",
    "            if u.bit[k]==None:\n",
    "                u.bit[k]=tr_node()\n",
    "            u=u.bit[k]\n",
    "            u.sum+=1\n",
    "            i-=1\n",
    "    def query(self,x,k):\n",
    "        ans=0\n",
    "        u=self.root\n",
    "        i=24\n",
    "        while i>=0:\n",
    "            kb=k>>i&1\n",
    "            cb=x>>i&1\n",
    "            if kb==1:\n",
    "                if u.bit[cb]:\n",
    "                    ans+=u.bit[cb].sum\n",
    "                if u.bit[cb^1]==None:\n",
    "                    return ans\n",
    "                u=u.bit[cb^1]\n",
    "            else:\n",
    "                if u.bit[cb]==None:\n",
    "                    return ans\n",
    "                u=u.bit[cb]\n",
    "            i-=1\n",
    "        ans+=u.sum\n",
    "        return ans\n",
    "        \n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, nums: List[int], low: int, high: int) -> int:\n",
    "        ans=0\n",
    "        n=len(nums)\n",
    "        tr=trie_01()\n",
    "        for i in nums:\n",
    "            ans+=tr.query(i,high)-tr.query(i,low-1)\n",
    "            tr.insert(i)\n",
    "        return ans"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "HIGH_BIT = 14\n",
    "\n",
    "class TrieNode:\n",
    "    def __init__(self):\n",
    "        self.children = [None, None]\n",
    "        self.sum = 0\n",
    "\n",
    "class Trie:\n",
    "    def __init__(self):\n",
    "        self.root = TrieNode()\n",
    "\n",
    "    def add(self, num: int) -> None:\n",
    "        cur = self.root\n",
    "        for k in range(HIGH_BIT, -1, -1):\n",
    "            bit = (num >> k) & 1\n",
    "            if not cur.children[bit]:\n",
    "                cur.children[bit] = TrieNode()\n",
    "            cur = cur.children[bit]\n",
    "            cur.sum += 1\n",
    "\n",
    "    def get(self, num: int, x: int) -> int:\n",
    "        res = 0\n",
    "        cur = self.root\n",
    "        for k in range(HIGH_BIT, -1, -1):\n",
    "            bit = (num >> k) & 1\n",
    "            if (x >> k) & 1:\n",
    "                if cur.children[bit]:\n",
    "                    res += cur.children[bit].sum\n",
    "                if not cur.children[bit ^ 1]:\n",
    "                    return res\n",
    "                cur = cur.children[bit ^ 1]\n",
    "            else:\n",
    "                if not cur.children[bit]:\n",
    "                    return res\n",
    "                cur = cur.children[bit]\n",
    "        res += cur.sum\n",
    "        return res\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, nums: List[int], low: int, high: int) -> int:\n",
    "        def f(nums: List[int], x: int) -> int:\n",
    "            res = 0\n",
    "            trie = Trie()\n",
    "            for i in range(1, len(nums)):\n",
    "                trie.add(nums[i - 1])\n",
    "                res += trie.get(nums[i], x)\n",
    "            return res\n",
    "        return f(nums, high) - f(nums, low - 1)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Trie:\n",
    "    def __init__(self):        \n",
    "        self.child = [None, None]\n",
    "        self.count = 0\n",
    "    \n",
    "class Solution:\n",
    "    def countPairs(self, nums: List[int], low: int, high: int) -> int:\n",
    "        def insert(root: Optional[Trie], n: int) -> NoReturn:\n",
    "            for i in range(31, -1, -1):\n",
    "                x = bool((n) & (1 << i))\n",
    "                if not root.child[x]:\n",
    "                    root.child[x] = Trie()\n",
    "                root.child[x].count += 1\n",
    "                root = root.child[x]\n",
    "\n",
    "        def count_k(root: Optional[Trie], n: int, k: int) -> int:\n",
    "            result = 0\n",
    "            for i in range(31, -1, -1):       \n",
    "                if not root:\n",
    "                    break                       \n",
    "                x = bool(n & (1 << i))\n",
    "                y = k & (1 << i)\n",
    "                if y:\n",
    "                    if root.child[x]:\n",
    "                        result += root.child[x].count\n",
    "                    root = root.child[1 - x]\n",
    "                else:\n",
    "                    root = root.child[x]\n",
    "            return result\n",
    "        root = Trie()\n",
    "        result = 0\n",
    "        for num in nums:\n",
    "            result += count_k(root, num, high + 1) - count_k(root, num, low)\n",
    "            insert(root, num)\n",
    "        return result"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, nums: List[int], low: int, high: int) -> int:\n",
    "        trie = Trie()\n",
    "        ans = 0\n",
    "        for i in nums:\n",
    "            \n",
    "            a = trie.search(i, high + 1) - trie.search(i, low)\n",
    "          \n",
    "            ans += a\n",
    "            trie.insert(i)\n",
    "\n",
    "        return ans\n",
    "\n",
    "K = 14        \n",
    "class Trie:\n",
    "    \n",
    "    def __init__(self):\n",
    "        self.children = [None] * 2\n",
    "        self.cnt = 0 # 统计漂亮数对的个数\n",
    "    \n",
    "    def insert(self, x):\n",
    "        node = self\n",
    "        # for i in range(K, -1, -1):\n",
    "        #     ch = (x >> K) & 1\n",
    "        #     if node.children[ch] is None:\n",
    "        #         node.children[ch] = Trie()\n",
    "        #     node = node.children[ch]\n",
    "        #     node.cnt += 1\n",
    "        for k in range(14, -1, -1):\n",
    "            v = (x >> k) & 1\n",
    "            if node.children[v] is None:\n",
    "                node.children[v] = Trie()\n",
    "            # node.cnt += 1 # 我觉得在前面加一和后面加一效果差不多\n",
    "            # 关于在前在后加一，可以使用边界判断的方法\n",
    "            # 对于叶子节点，前置位放置此语句叶子结点值不会改变\n",
    "            node = node.children[v]\n",
    "            node.cnt += 1\n",
    "\n",
    "    def search(self, x, compare):\n",
    "        # 每次插入一个元素，从高位到低位计算异或值\n",
    "        # 如果f(x, compare):表示x和compare的比较,\n",
    "        # 比较二者之间的异或值，\n",
    "        ans = 0\n",
    "        node = self\n",
    "        for i in range(K, -1, -1):\n",
    "            \n",
    "            if node is None:\n",
    "                return ans\n",
    "\n",
    "            ch = (x >> i) & 1\n",
    "            if (compare >> i) & 1: # 若是1的话，对于任何x的当前位数都满足小于等于compare\n",
    "                if node.children[ch] is not None: # 说明两数在当前位是相同的，1 xor 1 = 0，直接返回当前结点下的所有数即可\n",
    "                    ans += node.children[ch].cnt\n",
    "                node = node.children[ch^1]\n",
    "            else: # 若是0的话，当且仅当，两数当前位相同的情况下，才有可能进行\n",
    "                node = node.children[ch]\n",
    "        return ans \n",
    "        # node = self\n",
    "        # ans = 0\n",
    "        \n",
    "        # for k in range(14, -1, -1):\n",
    "        #     if node is None:\n",
    "        #         return ans\n",
    "        #     v = (num >> k) & 1\n",
    "            \n",
    "        #     if (x >> k) & 1: # 第k位为1\n",
    "        #         if node.children[v] is not None: # 异或值为0，一定满足小于x\n",
    "        #             ans += node.children[v].cnt\n",
    "        #         node = node.children[v ^ 1] # 对于异或值为1的存在可能满足小于等于x\n",
    "        #     else: # 第k位为0\n",
    "        #         node = node.children[v] # 只有异或值为0时才存在满足的可能\n",
    "        \n",
    "        # return ans\n",
    "\n",
    "        \"\"\"\n",
    "            使用下面这种思路可行吗。\n",
    "        \"\"\"\n",
    "        # def search(self, x, low, high):\n",
    "        # # 每次插入一个元素，从高位到低位计算异或值\n",
    "        # # 如果\n",
    "        # ans = 0\n",
    "        # node = self\n",
    "        # for i in range(K, -1, -1):\n",
    "        #     ch = (x >> K) & 1\n",
    "        #     if node.children[ch]: # 位上元素相同，返回1 xor 1 = 0， 0 xor 0 = 0\n",
    "        #         if ((low >> K) & 1): # 若low值的第K位为1，则两数之间的异或值必不可能大于low值，可直接break\n",
    "        #             return 0\n",
    "        #         node = node.children[ch]\n",
    "        #     else: # 位上元素不同，返回1 xor 0 = 1\n",
    "        #         # 这种情况只需判断是否小于等于high即可\n",
    "        #         if (high >>k) & 1 == 0:\n",
    "        #             return 0\n",
    "                \n",
    "            \n",
    "        #     return 1\n",
    "\n",
    "\n",
    "            # if node.children[ch]: # 位上元素相同，返回1 xor 1 = 0， 0 xor 0 = 0\n",
    "            #     node = node.children[ch]\n",
    "            # else: # 位上元素不同，返回1 xor 0 = 1\n",
    "            #     # 这种情况只需判断是否小于等于high即可\n",
    "            #     if (compare >> k) & 1 == 1:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Tire:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.children = [None] * 2\n",
    "        self.cnt = 0\n",
    "\n",
    "    def insert(self, num):\n",
    "        node = self\n",
    "        for i in range(15, -1, -1):\n",
    "            v = num >> i & 1\n",
    "            if not node.children[v]:\n",
    "                node.children[v] = Tire()\n",
    "            node = node.children[v]\n",
    "            node.cnt += 1\n",
    "    \n",
    "    def search(self, num, limit):\n",
    "        node = self\n",
    "        res = 0\n",
    "        for i in range(15, -1, -1):\n",
    "            v = num >> i & 1\n",
    "            if limit >> i & 1:\n",
    "                if node.children[v]:\n",
    "                    res += node.children[v].cnt\n",
    "                if not node.children[v ^ 1]:\n",
    "                    return res\n",
    "                node = node.children[v ^ 1]\n",
    "            else:\n",
    "                if not node.children[v]:\n",
    "                    return res\n",
    "                node = node.children[v]\n",
    "        return res\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, nums: List[int], low: int, high: int) -> int:\n",
    "\n",
    "        ans = 0\n",
    "        t = Tire()\n",
    "        for num in nums:\n",
    "            ans += t.search(num, high + 1) - t.search(num, low)\n",
    "            t.insert(num)\n",
    "\n",
    "        return ans "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "HIGH_BIT = 14\n",
    "\n",
    "class TrieNode:\n",
    "    def __init__(self):\n",
    "        self.children = [None, None]\n",
    "        self.sum = 0\n",
    "\n",
    "class Trie:\n",
    "    def __init__(self):\n",
    "        self.root = TrieNode()\n",
    "    \n",
    "    def add(self, num: int) -> None:\n",
    "        cur = self.root\n",
    "        for k in range(HIGH_BIT, -1, -1):\n",
    "            bit = (num >> k) & 1\n",
    "            if not cur.children[bit]:\n",
    "                cur.children[bit] = TrieNode()\n",
    "            cur = cur.children[bit]\n",
    "            cur.sum += 1\n",
    "    \n",
    "    def get(self, num: int, x: int) -> int:\n",
    "        res = 0\n",
    "        cur = self.root\n",
    "        for k in range(HIGH_BIT, -1, -1):\n",
    "            bit = (num >> k) & 1\n",
    "            if (x >> k) & 1:\n",
    "                if cur.children[bit]:\n",
    "                    res += cur.children[bit].sum\n",
    "                if not cur.children[bit ^ 1]:\n",
    "                    return res\n",
    "                cur = cur.children[bit ^ 1]\n",
    "            else:\n",
    "                if not cur.children[bit]:\n",
    "                    return res\n",
    "                cur = cur.children[bit]\n",
    "        res += cur.sum\n",
    "        return res\n",
    "\n",
    "\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, nums: List[int], low: int, high: int) -> int:\n",
    "        def find(nums: List[int], x: int) -> int:\n",
    "            res = 0\n",
    "            trie = Trie()\n",
    "            for i in range(1, len(nums)):\n",
    "                trie.add(nums[i - 1])\n",
    "                res += trie.get(nums[i], x)\n",
    "\n",
    "            return res\n",
    "        \n",
    "        return find(nums, high) - find(nums, low - 1)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Trie:\n",
    "    def __init__(self):\n",
    "        self.children = [None] * 2\n",
    "        self.cnt = 0\n",
    "\n",
    "    def insert(self, x):\n",
    "        node = self\n",
    "        for i in range(15, -1, -1):\n",
    "            v = x >> i & 1\n",
    "            if node.children[v] is None:\n",
    "                node.children[v] = Trie()\n",
    "            node = node.children[v]\n",
    "            node.cnt += 1\n",
    "\n",
    "    def search(self, x, limit):\n",
    "        node = self\n",
    "        ans = 0\n",
    "        for i in range(15, -1, -1):\n",
    "            if node is None:\n",
    "                return ans\n",
    "            v = x >> i & 1\n",
    "            if limit >> i & 1:\n",
    "                if node.children[v]:\n",
    "                    ans += node.children[v].cnt\n",
    "                node = node.children[v ^ 1]\n",
    "            else:\n",
    "                node = node.children[v]\n",
    "        return ans\n",
    "\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, nums: List[int], low: int, high: int) -> int:\n",
    "        ans = 0\n",
    "        tree = Trie()\n",
    "        for x in nums:\n",
    "            ans += tree.search(x, high + 1) - tree.search(x, low)\n",
    "            tree.insert(x)\n",
    "        return ans"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Trie:\n",
    "    def __init__(self):\n",
    "        self.root = {}\n",
    "    \n",
    "    def add(self, num):\n",
    "        node = self.root\n",
    "        for i in range(14, -1, -1):\n",
    "            bit = (num >> i) & 1\n",
    "            node[bit] = node.get(bit, {})\n",
    "            node = node[bit]\n",
    "            node['#'] = node.get('#', 0) + 1\n",
    "    \n",
    "    def search(self, num, limit):\n",
    "        node = self.root\n",
    "        count = 0\n",
    "        for i in range(14, -1, -1):\n",
    "            bit = (num >> i) & 1\n",
    "            if (limit >> i) & 1 == 0:\n",
    "                if bit in node:\n",
    "                    node = node[bit]\n",
    "                else:\n",
    "                    return count\n",
    "            else:\n",
    "                if bit in node:\n",
    "                    count += node[bit]['#']\n",
    "                if bit ^ 1 in node:\n",
    "                    node = node[bit ^ 1]\n",
    "                else:\n",
    "                    return count\n",
    "        return count + node['#']\n",
    "\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, nums: List[int], low: int, high: int) -> int:\n",
    "        n = len(nums)\n",
    "        def count(limit):\n",
    "            trie = Trie()\n",
    "            count = 0\n",
    "            for i in range(1, n):\n",
    "                trie.add(nums[i - 1])\n",
    "                count += trie.search(nums[i], limit)\n",
    "            return count\n",
    "        return count(high) - count(low - 1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Trie:\n",
    "    def __init__(self):\n",
    "        self.bits = [None]*2\n",
    "        self.cnt = 0\n",
    "\n",
    "    def add(self, num):\n",
    "        # 15\n",
    "        cur = self\n",
    "        for i in range(14, -1, -1):\n",
    "            if num&(1<<i) and cur.bits[1] is None:\n",
    "                cur.bits[1] = Trie()\n",
    "            elif num&(1<<i) == 0 and cur.bits[0] is None:\n",
    "                cur.bits[0] = Trie()\n",
    "            t = 1 if num&(1<<i) else 0\n",
    "            cur.cnt += 1\n",
    "            cur = cur.bits[t]\n",
    "        cur.cnt += 1\n",
    "\n",
    "    def search(self, num, x):\n",
    "        ans = 0\n",
    "        cur = self\n",
    "        for i in range(14, -1, -1):\n",
    "            if cur is None: break\n",
    "            if x & (1<<i):\n",
    "                ans += cur.bits[1 if num&(1<<i) else 0].cnt if cur.bits[1 if num&(1<<i) else 0] else 0\n",
    "                cur = cur.bits[0 if num&(1<<i) else 1]\n",
    "            else:\n",
    "                cur = cur.bits[1 if num&(1<<i) else 0]\n",
    "\n",
    "        return ans+cur.cnt if cur else ans\n",
    "\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, nums: List[int], low: int, high: int) -> int:\n",
    "        # x为1，两个相同可以放到结果中。都为0或者都为1。\n",
    "        # 表示前缀以及当前的。那么表示这么个前缀的有多少个数。\n",
    "        # x为0，不到计算结果的时候，往下走。\n",
    "\n",
    "        # 如果为0，那么就到下一位。\n",
    "\n",
    "        def f(x):\n",
    "            t = Trie()\n",
    "            ans = 0\n",
    "            for num in nums:\n",
    "                t.add(num)\n",
    "                ans += t.search(num, x)\n",
    "            return ans\n",
    "\n",
    "        return f(high)-f(low-1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "HIGH_BIT = 14\n",
    "\n",
    "class TrieNode:\n",
    "    def __init__(self):\n",
    "        self.children = [None, None]\n",
    "        self.sum = 0\n",
    "\n",
    "class Trie:\n",
    "    def __init__(self):\n",
    "        self.root = TrieNode()\n",
    "\n",
    "    def add(self, num: int) -> None:\n",
    "        cur = self.root\n",
    "        for k in range(HIGH_BIT, -1, -1):\n",
    "            bit = (num >> k) & 1\n",
    "            if not cur.children[bit]:\n",
    "                cur.children[bit] = TrieNode()\n",
    "            cur = cur.children[bit]\n",
    "            cur.sum += 1\n",
    "\n",
    "    def get(self, num: int, x: int) -> int:\n",
    "        res = 0\n",
    "        cur = self.root\n",
    "        for k in range(HIGH_BIT, -1, -1):\n",
    "            bit = (num >> k) & 1\n",
    "            if (x >> k) & 1:\n",
    "                if cur.children[bit]:\n",
    "                    res += cur.children[bit].sum\n",
    "                if not cur.children[bit ^ 1]:\n",
    "                    return res\n",
    "                cur = cur.children[bit ^ 1]\n",
    "            else:\n",
    "                if not cur.children[bit]:\n",
    "                    return res\n",
    "                cur = cur.children[bit]\n",
    "        res += cur.sum\n",
    "        return res\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, nums: List[int], low: int, high: int) -> int:\n",
    "        def f(nums: List[int], x: int) -> int:\n",
    "            res = 0\n",
    "            trie = Trie()\n",
    "            for i in range(1, len(nums)):\n",
    "                trie.add(nums[i - 1])\n",
    "                res += trie.get(nums[i], x)\n",
    "            return res\n",
    "        return f(nums, high) - f(nums, low - 1)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "\"\"\"Xor Trie 最大异或前缀树\"\"\"\n",
    "\n",
    "from typing import List\n",
    "\n",
    "\n",
    "class BinaryTrie:\n",
    "    __slots__ = (\n",
    "        \"_maxLog\",\n",
    "        \"_xEnd\",\n",
    "        \"_vList\",\n",
    "        \"_multiset\",\n",
    "        \"_edges\",\n",
    "        \"_size\",\n",
    "        \"_endCount\",\n",
    "        \"_maxV\",\n",
    "        \"_lazy\",\n",
    "    )\n",
    "\n",
    "    def __init__(self, max=1 << 30, addLimit=int(2e5 + 10), allowMultipleElements=True):\n",
    "        \"\"\"\n",
    "        Example:\n",
    "\n",
    "        ```\n",
    "        n = len(nums)\n",
    "        bt = BinaryTrie(max = 1 << 30, addLimit=n, allowMultipleElements=True)\n",
    "        for num in nums:\n",
    "            bt.add(num)\n",
    "        res = 0\n",
    "        for num in nums:\n",
    "            bt.xor_all(num)\n",
    "            res += bt.bisect_right(high) - bt.bisect_left(low)\n",
    "            bt.xor_all(num)\n",
    "        ```\n",
    "        \"\"\"\n",
    "        maxLog = max.bit_length()\n",
    "        self._maxLog = maxLog\n",
    "        self._xEnd = 1 << maxLog\n",
    "        self._vList = [0] * (maxLog + 1)\n",
    "        self._multiset = allowMultipleElements\n",
    "        n = maxLog * addLimit + 1\n",
    "        self._edges = [-1] * (2 * n)\n",
    "        self._size = [0] * n\n",
    "        self._endCount = [0] * n\n",
    "        self._maxV = 0\n",
    "        self._lazy = 0\n",
    "\n",
    "    def add(self, x: int) -> None:\n",
    "        x ^= self._lazy\n",
    "        v = 0\n",
    "        for i in range(self._maxLog - 1, -1, -1):\n",
    "            d = (x >> i) & 1\n",
    "            if self._edges[2 * v + d] == -1:\n",
    "                self._maxV += 1\n",
    "                self._edges[2 * v + d] = self._maxV\n",
    "            v = self._edges[2 * v + d]\n",
    "            self._vList[i] = v\n",
    "        if self._multiset or self._endCount[v] == 0:\n",
    "            self._endCount[v] += 1\n",
    "            for v in self._vList:\n",
    "                self._size[v] += 1\n",
    "\n",
    "    def discard(self, x: int) -> None:\n",
    "        if not 0 <= x < self._xEnd:\n",
    "            return\n",
    "        x ^= self._lazy\n",
    "        v = 0\n",
    "        for i in range(self._maxLog - 1, -1, -1):\n",
    "            d = (x >> i) & 1\n",
    "            if self._edges[2 * v + d] == -1:\n",
    "                return\n",
    "            v = self._edges[2 * v + d]\n",
    "            self._vList[i] = v\n",
    "        if self._endCount[v] > 0:\n",
    "            self._endCount[v] -= 1\n",
    "            for v in self._vList:\n",
    "                self._size[v] -= 1\n",
    "\n",
    "    def erase(self, x: int, count=1):\n",
    "        \"\"\"删除count个x.count=-1表示删除所有x.\"\"\"\n",
    "        if not 0 <= x < self._xEnd:\n",
    "            return\n",
    "        x ^= self._lazy\n",
    "        v = 0\n",
    "        for i in range(self._maxLog - 1, -1, -1):\n",
    "            d = (x >> i) & 1\n",
    "            if self._edges[2 * v + d] == -1:\n",
    "                return\n",
    "            v = self._edges[2 * v + d]\n",
    "            self._vList[i] = v\n",
    "        if count == -1 or self._endCount[v] < count:\n",
    "            count = self._endCount[v]\n",
    "        if self._endCount[v] > 0:\n",
    "            self._endCount[v] -= count\n",
    "            for v in self._vList:\n",
    "                self._size[v] -= count\n",
    "\n",
    "    def count(self, x: int) -> int:\n",
    "        if not 0 <= x < self._xEnd:\n",
    "            return 0\n",
    "        x ^= self._lazy\n",
    "        v = 0\n",
    "        for i in range(self._maxLog - 1, -1, -1):\n",
    "            d = (x >> i) & 1\n",
    "            if self._edges[2 * v + d] == -1:\n",
    "                return 0\n",
    "            v = self._edges[2 * v + d]\n",
    "        return self._endCount[v]\n",
    "\n",
    "    def bisectLeft(self, x: int) -> int:\n",
    "        if x < 0:\n",
    "            return 0\n",
    "        if self._xEnd <= x:\n",
    "            return len(self)\n",
    "        v = 0\n",
    "        ret = 0\n",
    "        for i in range(self._maxLog - 1, -1, -1):\n",
    "            d = (x >> i) & 1\n",
    "            left = (self._lazy >> i) & 1\n",
    "            lc = self._edges[2 * v]\n",
    "            rc = self._edges[2 * v + 1]\n",
    "            if left == 1:\n",
    "                lc, rc = rc, lc\n",
    "            if d:\n",
    "                if lc != -1:\n",
    "                    ret += self._size[lc]\n",
    "                if rc == -1:\n",
    "                    return ret\n",
    "                v = rc\n",
    "            else:\n",
    "                if lc == -1:\n",
    "                    return ret\n",
    "                v = lc\n",
    "        return ret\n",
    "\n",
    "    def bisectRight(self, x: int) -> int:\n",
    "        return self.bisectLeft(x + 1)\n",
    "\n",
    "    def index(self, x: int) -> int:\n",
    "        if x not in self:\n",
    "            raise ValueError(f\"{x} is not in BinaryTrie\")\n",
    "        return self.bisectLeft(x)\n",
    "\n",
    "    def find(self, x: int) -> int:\n",
    "        if x not in self:\n",
    "            return -1\n",
    "        return self.bisectLeft(x)\n",
    "\n",
    "    def at(self, index: int) -> int:\n",
    "        if index < 0:\n",
    "            index += self._size[0]\n",
    "        v = 0\n",
    "        ret = 0\n",
    "        for i in range(self._maxLog - 1, -1, -1):\n",
    "            left = (self._lazy >> i) & 1\n",
    "            lc = self._edges[2 * v]\n",
    "            rc = self._edges[2 * v + 1]\n",
    "            if left == 1:\n",
    "                lc, rc = rc, lc\n",
    "            if lc == -1:\n",
    "                v = rc\n",
    "                ret |= 1 << i\n",
    "                continue\n",
    "            if self._size[lc] <= index:\n",
    "                index -= self._size[lc]\n",
    "                v = rc\n",
    "                ret |= 1 << i\n",
    "            else:\n",
    "                v = lc\n",
    "        return ret\n",
    "\n",
    "    def minimum(self) -> int:\n",
    "        return self.at(0)\n",
    "\n",
    "    def maximum(self) -> int:\n",
    "        return self.at(-1)\n",
    "\n",
    "    def xor_all(self, x: int) -> None:\n",
    "        self._lazy ^= x\n",
    "\n",
    "    def __iter__(self):\n",
    "        q = [(0, 0)]\n",
    "        for i in range(self._maxLog - 1, -1, -1):\n",
    "            left = (self._lazy >> i) & 1\n",
    "            nq = []\n",
    "            for v, x in q:\n",
    "                lc = self._edges[2 * v]\n",
    "                rc = self._edges[2 * v + 1]\n",
    "                if left == 1:\n",
    "                    lc, rc = rc, lc\n",
    "                if lc != -1:\n",
    "                    nq.append((lc, 2 * x))\n",
    "                if rc != -1:\n",
    "                    nq.append((rc, 2 * x + 1))\n",
    "            q = nq\n",
    "        for v, x in q:\n",
    "            for _ in range(self._endCount[v]):\n",
    "                yield x\n",
    "\n",
    "    def __str__(self) -> str:\n",
    "        prefix = \"BinaryTrie(\"\n",
    "        content = list(map(str, self))\n",
    "        suffix = \")\"\n",
    "        if content:\n",
    "            content[0] = prefix + content[0]\n",
    "            content[-1] = content[-1] + suffix\n",
    "        else:\n",
    "            content = [prefix + suffix]\n",
    "        return \", \".join(content)\n",
    "\n",
    "    def __getitem__(self, k: int) -> int:\n",
    "        return self.at(k)\n",
    "\n",
    "    def __contains__(self, x: int) -> bool:\n",
    "        return not not self.count(x)\n",
    "\n",
    "    def __len__(self) -> int:\n",
    "        return self._size[0]\n",
    "\n",
    "    def __bool__(self) -> bool:\n",
    "        return not not len(self)\n",
    "\n",
    "    def __ixor__(self, x: int) -> \"BinaryTrie\":\n",
    "        self.xor_all(x)\n",
    "        return self\n",
    "\n",
    "\n",
    "if __name__ == \"__main__\":\n",
    "\n",
    "\n",
    "    # 1803. 统计异或值在范围内的数对有多少\n",
    "    class Solution:\n",
    "        def countPairs(self, nums: List[int], low: int, high: int) -> int:\n",
    "            n = len(nums)\n",
    "            bt = BinaryTrie(max=max(nums), addLimit=n, allowMultipleElements=True)\n",
    "            for num in nums:\n",
    "                bt.add(num)\n",
    "            res = 0\n",
    "            for num in nums:\n",
    "                bt.xor_all(num)\n",
    "                res += bt.bisectRight(high) - bt.bisectLeft(low)\n",
    "                bt.xor_all(num)\n",
    "            return res // 2\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Node:\n",
    "    def __init__(self):\n",
    "        self.nxt = defaultdict(Node)\n",
    "        self.cnt = 0\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, nums: List[int], low: int, high: int) -> int:\n",
    "        def get(root, x, t):\n",
    "            cur = root\n",
    "            ans = 0\n",
    "            for i in range(14, -1, -1):\n",
    "                if not cur: break\n",
    "                bit = x>>i&1\n",
    "                if t>>i&1:\n",
    "                    if bit in cur.nxt:\n",
    "                        ans += cur.nxt[bit].cnt\n",
    "                    if bit^1 not in cur.nxt:\n",
    "                        return ans\n",
    "                    cur = cur.nxt[bit^1]\n",
    "                else:\n",
    "                    if bit not in cur.nxt:\n",
    "                        return ans\n",
    "                    cur = cur.nxt[bit]\n",
    "            return ans\n",
    "            \n",
    "        def cal(t):\n",
    "            root = Node()\n",
    "            ans = 0\n",
    "            for x in nums:\n",
    "                ans += get(root, x, t)\n",
    "                cur = root\n",
    "                for i in range(14, -1, -1):\n",
    "                    cur = cur.nxt[x>>i&1]\n",
    "                    cur.cnt += 1\n",
    "            return ans\n",
    "        \n",
    "        return cal(high+1) - cal(low)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Node:\n",
    "    def __init__(self):\n",
    "        self.nxt = defaultdict(Node)\n",
    "        self.cnt = 0\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, nums: List[int], low: int, high: int) -> int:\n",
    "        def get(root, x, t):\n",
    "            cur = root\n",
    "            ans = 0\n",
    "            for i in range(14, -1, -1):\n",
    "                if not cur: break\n",
    "                bit = x>>i&1\n",
    "                if t>>i&1:\n",
    "                    if bit in cur.nxt:\n",
    "                        ans += cur.nxt[bit].cnt\n",
    "                    if bit^1 not in cur.nxt: return ans\n",
    "                    cur = cur.nxt[bit^1]\n",
    "                else:\n",
    "                    if bit not in cur.nxt: return ans\n",
    "                    cur = cur.nxt[bit]\n",
    "            return ans\n",
    "            \n",
    "        def cal(t):\n",
    "            root = Node()\n",
    "            ans = 0\n",
    "            for x in nums:\n",
    "                ans += get(root, x, t)\n",
    "                cur = root\n",
    "                for i in range(14, -1, -1):\n",
    "                    cur = cur.nxt[x>>i&1]\n",
    "                    cur.cnt += 1\n",
    "            return ans\n",
    "        \n",
    "        return cal(high+1) - cal(low)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "HIGH_BIT = 15\n",
    "class Trie:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.children = defaultdict(Trie)\n",
    "        self.cnt = 0\n",
    "\n",
    "    def insert(self, x):\n",
    "        cur = self\n",
    "        for i in range(HIGH_BIT - 1, -1, -1):\n",
    "            if (x >> i) & 1:\n",
    "                cur = cur.children[1]\n",
    "            else:\n",
    "                cur = cur.children[0]\n",
    "            cur.cnt += 1\n",
    "\n",
    "    def search(self, x, limit):\n",
    "        ans = 0\n",
    "        cur = self\n",
    "        for i in range(HIGH_BIT - 1, -1, -1):\n",
    "            if not cur.children:\n",
    "                return ans\n",
    "            v = (x >> i) & 1\n",
    "            u = (limit >> i) & 1\n",
    "            if u:\n",
    "                if cur.children[v]:\n",
    "                    ans += cur.children[v].cnt\n",
    "                cur = cur.children[v ^ 1]\n",
    "            else:\n",
    "                cur = cur.children[v]\n",
    "        return ans\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, nums: List[int], low: int, high: int) -> int:\n",
    "        tree = Trie()\n",
    "        res = 0\n",
    "        for x in nums:\n",
    "            res += tree.search(x, high + 1) - tree.search(x, low)\n",
    "            tree.insert(x)\n",
    "        return res"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "HIGH_BIT = 15\n",
    "class Trie:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.children = defaultdict(Trie)\n",
    "        self.cnt = 0\n",
    "\n",
    "    def insert(self, x):\n",
    "        cur = self\n",
    "        for i in range(HIGH_BIT - 1, -1, -1):\n",
    "            if (x >> i) & 1:\n",
    "                cur = cur.children[1]\n",
    "            else:\n",
    "                cur = cur.children[0]\n",
    "            cur.cnt += 1\n",
    "\n",
    "    def search(self, x, limit):\n",
    "        ans = 0\n",
    "        cur = self\n",
    "        for i in range(HIGH_BIT - 1, -1, -1):\n",
    "            if not cur.children:\n",
    "                return ans\n",
    "            v = (x >> i) & 1\n",
    "            u = (limit >> i) & 1\n",
    "            if u:\n",
    "                if cur.children[v]:\n",
    "                    ans += cur.children[v].cnt\n",
    "                cur = cur.children[v ^ 1]\n",
    "            else:\n",
    "                cur = cur.children[v]\n",
    "        return ans\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, nums: List[int], low: int, high: int) -> int:\n",
    "        tree = Trie()\n",
    "        res = 0\n",
    "        for x in nums:\n",
    "            res += tree.search(x, high + 1) - tree.search(x, low)\n",
    "            tree.insert(x)\n",
    "        return res"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, nums: List[int], low: int, high: int) -> int:\n",
    "        return self.f(nums, high) - self.f(nums, low-1)\n",
    "\n",
    "    \n",
    "    def f(self, nums, lim):\n",
    "        n = len(nums)\n",
    "        tr = [[0, 0] for _ in range(n * 20 + 5)]\n",
    "        num = [0] * (n*20+5)\n",
    "        cnt, ans = 1, 0\n",
    "\n",
    "        def insert(x):\n",
    "            nonlocal num, tr, cnt\n",
    "            cur = 1\n",
    "            for i in range(16, -1, -1):\n",
    "                t = x >> i & 1\n",
    "                if tr[cur][t] == 0:\n",
    "                    cnt += 1\n",
    "                    tr[cur][t] = cnt\n",
    "                cur = tr[cur][t]\n",
    "                num[cur] += 1\n",
    "        \n",
    "        def query(x):\n",
    "            cur = 1\n",
    "            res = 0\n",
    "            for i in range(16, -1, -1):\n",
    "                t0, t1 = x >> i & 1, lim >> i & 1\n",
    "                t = t0^t1\n",
    "                if t1 == 1:\n",
    "                    res += num[tr[cur][t0]]\n",
    "                if tr[cur][t] == 0:\n",
    "                    return res\n",
    "                cur = tr[cur][t]\n",
    "            return res + num[cur]\n",
    "        \n",
    "        for i in range(n):\n",
    "            ans += query(nums[i])\n",
    "            insert(nums[i])\n",
    "        \n",
    "        return ans\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "\"\"\"Xor Trie 最大异或前缀树\"\"\"\n",
    "\n",
    "from typing import List\n",
    "\n",
    "\n",
    "class BinaryTrie:\n",
    "    __slots__ = (\n",
    "        \"_maxLog\",\n",
    "        \"_xEnd\",\n",
    "        \"_vList\",\n",
    "        \"_multiset\",\n",
    "        \"_edges\",\n",
    "        \"_size\",\n",
    "        \"_endCount\",\n",
    "        \"_maxV\",\n",
    "        \"_lazy\",\n",
    "    )\n",
    "\n",
    "    def __init__(self, max=1 << 30, addLimit=int(2e5 + 10), allowMultipleElements=True):\n",
    "        \"\"\"\n",
    "        Example:\n",
    "\n",
    "        ```\n",
    "        n = len(nums)\n",
    "        bt = BinaryTrie(max = 1 << 30, addLimit=n, allowMultipleElements=True)\n",
    "        for num in nums:\n",
    "            bt.add(num)\n",
    "        res = 0\n",
    "        for num in nums:\n",
    "            bt.xor_all(num)\n",
    "            res += bt.bisect_right(high) - bt.bisect_left(low)\n",
    "            bt.xor_all(num)\n",
    "        ```\n",
    "        \"\"\"\n",
    "        maxLog = max.bit_length()\n",
    "        self._maxLog = maxLog\n",
    "        self._xEnd = 1 << maxLog\n",
    "        self._vList = [0] * (maxLog + 1)\n",
    "        self._multiset = allowMultipleElements\n",
    "        n = maxLog * addLimit + 1\n",
    "        self._edges = [-1] * (2 * n)\n",
    "        self._size = [0] * n\n",
    "        self._endCount = [0] * n\n",
    "        self._maxV = 0\n",
    "        self._lazy = 0\n",
    "\n",
    "    def add(self, x: int) -> None:\n",
    "        x ^= self._lazy\n",
    "        v = 0\n",
    "        for i in range(self._maxLog - 1, -1, -1):\n",
    "            d = (x >> i) & 1\n",
    "            if self._edges[2 * v + d] == -1:\n",
    "                self._maxV += 1\n",
    "                self._edges[2 * v + d] = self._maxV\n",
    "            v = self._edges[2 * v + d]\n",
    "            self._vList[i] = v\n",
    "        if self._multiset or self._endCount[v] == 0:\n",
    "            self._endCount[v] += 1\n",
    "            for v in self._vList:\n",
    "                self._size[v] += 1\n",
    "\n",
    "    def discard(self, x: int) -> None:\n",
    "        if not 0 <= x < self._xEnd:\n",
    "            return\n",
    "        x ^= self._lazy\n",
    "        v = 0\n",
    "        for i in range(self._maxLog - 1, -1, -1):\n",
    "            d = (x >> i) & 1\n",
    "            if self._edges[2 * v + d] == -1:\n",
    "                return\n",
    "            v = self._edges[2 * v + d]\n",
    "            self._vList[i] = v\n",
    "        if self._endCount[v] > 0:\n",
    "            self._endCount[v] -= 1\n",
    "            for v in self._vList:\n",
    "                self._size[v] -= 1\n",
    "\n",
    "    def erase(self, x: int, count=1):\n",
    "        \"\"\"删除count个x.count=-1表示删除所有x.\"\"\"\n",
    "        if not 0 <= x < self._xEnd:\n",
    "            return\n",
    "        x ^= self._lazy\n",
    "        v = 0\n",
    "        for i in range(self._maxLog - 1, -1, -1):\n",
    "            d = (x >> i) & 1\n",
    "            if self._edges[2 * v + d] == -1:\n",
    "                return\n",
    "            v = self._edges[2 * v + d]\n",
    "            self._vList[i] = v\n",
    "        if count == -1 or self._endCount[v] < count:\n",
    "            count = self._endCount[v]\n",
    "        if self._endCount[v] > 0:\n",
    "            self._endCount[v] -= count\n",
    "            for v in self._vList:\n",
    "                self._size[v] -= count\n",
    "\n",
    "    def count(self, x: int) -> int:\n",
    "        if not 0 <= x < self._xEnd:\n",
    "            return 0\n",
    "        x ^= self._lazy\n",
    "        v = 0\n",
    "        for i in range(self._maxLog - 1, -1, -1):\n",
    "            d = (x >> i) & 1\n",
    "            if self._edges[2 * v + d] == -1:\n",
    "                return 0\n",
    "            v = self._edges[2 * v + d]\n",
    "        return self._endCount[v]\n",
    "\n",
    "    def bisectLeft(self, x: int) -> int:\n",
    "        if x < 0:\n",
    "            return 0\n",
    "        if self._xEnd <= x:\n",
    "            return len(self)\n",
    "        v = 0\n",
    "        ret = 0\n",
    "        for i in range(self._maxLog - 1, -1, -1):\n",
    "            d = (x >> i) & 1\n",
    "            left = (self._lazy >> i) & 1\n",
    "            lc = self._edges[2 * v]\n",
    "            rc = self._edges[2 * v + 1]\n",
    "            if left == 1:\n",
    "                lc, rc = rc, lc\n",
    "            if d:\n",
    "                if lc != -1:\n",
    "                    ret += self._size[lc]\n",
    "                if rc == -1:\n",
    "                    return ret\n",
    "                v = rc\n",
    "            else:\n",
    "                if lc == -1:\n",
    "                    return ret\n",
    "                v = lc\n",
    "        return ret\n",
    "\n",
    "    def bisectRight(self, x: int) -> int:\n",
    "        return self.bisectLeft(x + 1)\n",
    "\n",
    "    def index(self, x: int) -> int:\n",
    "        if x not in self:\n",
    "            raise ValueError(f\"{x} is not in BinaryTrie\")\n",
    "        return self.bisectLeft(x)\n",
    "\n",
    "    def find(self, x: int) -> int:\n",
    "        if x not in self:\n",
    "            return -1\n",
    "        return self.bisectLeft(x)\n",
    "\n",
    "    def at(self, index: int) -> int:\n",
    "        if index < 0:\n",
    "            index += self._size[0]\n",
    "        v = 0\n",
    "        ret = 0\n",
    "        for i in range(self._maxLog - 1, -1, -1):\n",
    "            left = (self._lazy >> i) & 1\n",
    "            lc = self._edges[2 * v]\n",
    "            rc = self._edges[2 * v + 1]\n",
    "            if left == 1:\n",
    "                lc, rc = rc, lc\n",
    "            if lc == -1:\n",
    "                v = rc\n",
    "                ret |= 1 << i\n",
    "                continue\n",
    "            if self._size[lc] <= index:\n",
    "                index -= self._size[lc]\n",
    "                v = rc\n",
    "                ret |= 1 << i\n",
    "            else:\n",
    "                v = lc\n",
    "        return ret\n",
    "\n",
    "    def minimum(self) -> int:\n",
    "        return self.at(0)\n",
    "\n",
    "    def maximum(self) -> int:\n",
    "        return self.at(-1)\n",
    "\n",
    "    def xor_all(self, x: int) -> None:\n",
    "        self._lazy ^= x\n",
    "\n",
    "    def __iter__(self):\n",
    "        q = [(0, 0)]\n",
    "        for i in range(self._maxLog - 1, -1, -1):\n",
    "            left = (self._lazy >> i) & 1\n",
    "            nq = []\n",
    "            for v, x in q:\n",
    "                lc = self._edges[2 * v]\n",
    "                rc = self._edges[2 * v + 1]\n",
    "                if left == 1:\n",
    "                    lc, rc = rc, lc\n",
    "                if lc != -1:\n",
    "                    nq.append((lc, 2 * x))\n",
    "                if rc != -1:\n",
    "                    nq.append((rc, 2 * x + 1))\n",
    "            q = nq\n",
    "        for v, x in q:\n",
    "            for _ in range(self._endCount[v]):\n",
    "                yield x\n",
    "\n",
    "    def __str__(self) -> str:\n",
    "        prefix = \"BinaryTrie(\"\n",
    "        content = list(map(str, self))\n",
    "        suffix = \")\"\n",
    "        if content:\n",
    "            content[0] = prefix + content[0]\n",
    "            content[-1] = content[-1] + suffix\n",
    "        else:\n",
    "            content = [prefix + suffix]\n",
    "        return \", \".join(content)\n",
    "\n",
    "    def __getitem__(self, k: int) -> int:\n",
    "        return self.at(k)\n",
    "\n",
    "    def __contains__(self, x: int) -> bool:\n",
    "        return not not self.count(x)\n",
    "\n",
    "    def __len__(self) -> int:\n",
    "        return self._size[0]\n",
    "\n",
    "    def __bool__(self) -> bool:\n",
    "        return not not len(self)\n",
    "\n",
    "    def __ixor__(self, x: int) -> \"BinaryTrie\":\n",
    "        self.xor_all(x)\n",
    "        return self\n",
    "\n",
    "\n",
    "if __name__ == \"__main__\":\n",
    "    bt = BinaryTrie(max=1 << 30, addLimit=10**5, allowMultipleElements=True)\n",
    "    bt.add(20)\n",
    "    bt.add(1)\n",
    "    bt.add(2)\n",
    "    bt.add(21)\n",
    "    print(bt, bt.bisectLeft(2), bt.find(29))\n",
    "    bt.add(2)\n",
    "    bt.add(2)\n",
    "    bt.erase(2, -1)\n",
    "    print(bt, bt.bisectLeft(2), bt.find(29))\n",
    "\n",
    "    # 1803. 统计异或值在范围内的数对有多少\n",
    "    class Solution:\n",
    "        def countPairs(self, nums: List[int], low: int, high: int) -> int:\n",
    "            n = len(nums)\n",
    "            bt = BinaryTrie(max=max(nums), addLimit=n, allowMultipleElements=True)\n",
    "            for num in nums:\n",
    "                bt.add(num)\n",
    "            res = 0\n",
    "            for num in nums:\n",
    "                bt.xor_all(num)\n",
    "                res += bt.bisectRight(high) - bt.bisectLeft(low)\n",
    "                bt.xor_all(num)\n",
    "            return res // 2\n"
   ]
  }
 ],
 "metadata": {},
 "nbformat": 4,
 "nbformat_minor": 2
}
